現在の自宅LANに他所のサーバを一時的におくことになりました。
ただ、現在のLAN内には自宅サーバをおいてるので、インターネット←→自宅LANの間は構成は変えたくはありません。
また、他所サーバには自宅LAN内のPCにはアクセスできないようにします。
ということで、LANにルータをおいて、その先に他所サーバをおくことにしました。
ルータは CentOS を使って構築し、NAT の機能を有することにします。
構成図とはしては下記のような感じです。(元からある自宅LANが"ネットワークA"、今回追加したサーバ機のあるLANを"ネットワークB"としています。そして他所サーバは"サーバ機"として表記)
かなり、トリッキーなネットワークになっています。(普通はこんなことせずに、DMZ領域作るのが普通なんですが、なにせ自宅でリソースと時間がなかったので、この方法になりました。。。)
ネットワークカードを二つ用意し、片方を既存LAN側、もう片方を他所サーバをおくLANにします。
さて、LinuxでのNAT構築ですが、パケットフィルタに用いる iptables を使うようです。
ただ、ネットでNAT構築をググっても、NAPT(IPマスカレード)の構築方法は多いのですが、純粋なNAT(IPアドレスが1対1のもの)に関する情報は少なめでした。 (IPマスカレード使うときの方法については、@IT:natテーブルを利用したLinuxルータの作成(2/6)とかで解説されています。)
しかし、なんとか見つけたのが雑記 - iptablesによるNATです。
ということで、手順は下記のような感じになります。
IP Fowarding を有効にすると、複数のインターフェイス間でパケットの転送ができるようです。
/etc/sysctl.conf という設定ファイルを下記のように変更します。
net.ipv4.ip_forward=0
↓以下に修正
net.ipv4.ip_forward=1
そして、設定を反映するためにネットワークを再起動します。
# service network restart
(# sysctl -w net.ipv4.ip_forward=1 というコマンドでもIPフォワーディング有効にできるようですが、これだと再起動後には無効になるようです。)
現在、IPフォワーディングが有効になっているかどうかは、下記コマンドを叩き、1 が返ってくれば有効みたいですね。
cat /proc/sys/net/ipv4/ip_forward
2. 仮想インターフェイスを追加
下記コマンドにてネットワークA側のネットワークカードに仮想インターフェイスを追加します。
# cp /etc/sysconfig/network-scripts/ifcfg-eth0 /etc/sysconfig/network-scripts/ifcfg-eth0:1
# vi /etc/sysconfig/network-scripts/ifcfg-eth0:1
ここでIPを変更かつ、 DEVICE=eth0 を DEVICE=eth0:1 とし、設定ファイルを保存。
# ifup eth0:1
# ifconfig eth0:1
eth0:1 Link encap:Ethernet HWaddr 00:15:5D:00:64:0B
inet addr:192.168.0.11 Bcast:192.168.0.255 Mask:255.255.255.0
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
(最初は現在デフォルトゲートウェイにしているCTU(ルータ)にスタティックルーティングを設定して、ルータとなっているCentOSにパケットを回す予定だったんですが、CTUがWAN側にしかルーティングの設定ができないので仮想インターフェイスを追加します。)
3. iptables にNATの設定追加
iptablesのルールにNATの設定を追加します。iptablesのPREROUTINGチェインとPOSTROUTINGチェインを使います。
このあたりの話は、@IT:Linuxで作るファイアウォール[NAT設定編]とその次のページが非常に参考になります。
たとえば、こんな感じです。
#NATの設定リセット
iptables -t nat -F
#他所サーバ機から外に出ていくパケットを仮想インターフェイスのIPにアドレス変換
iptables -t nat -A POSTROUTING -s 192.168.1.2 -j SNAT --to 192.168.0.11
#仮想インターフェイスに入ってくるパケットを他所サーバ機のIPアドレスに変換(tcpとicmpのみ)(サーバのため)
iptables -t nat -A PREROUTING -d 192.168.0.11 -p tcp -j DNAT --to 192.168.1.2
iptables -t nat -A PREROUTING -d 192.168.0.11 -p icmp -j DNAT --to 192.168.1.2
また、他所サーバ機からネットワークA内のPCへのTCPアクセス接続を拒否する設定が要ります。
FORWARDチェインで設定できます。(参考:@IT:natテーブルを利用したLinuxルータの作成)
たとえば、こんな感じです。
#基本ポリシーとして、フォワーディング拒否
#ネットワークBからネットワークA内へのTCP新規接続拒否
iptables -A FORWARD -i eth1 -o eth0 -p tcp -m state --state NEW -s $any -d 192.168.0.0/24 -j DROP
#ネットワークBからネットワークA内への接続許可(上記TCP新規セッション以外のものが許可される)
iptables -A FORWARD -i eth1 -o eth0 -s 192.168.1.0/24 -j ACCEPT
#ネットワークAからネットワークBへの接続許可
iptables -A FORWARD -i eth0 -o eth1 -d 192.168.1.0/24 -j ACCEPT
#新規セッション以外の通信は許可
iptables -A FORWARD -m state --state ESTABLISHED,RELATED -j ACCEPT
とりえず、ネットワークBからネットワークAへの接続はTCPのみ遮断することとしました。
ただ、すべてのパケットを遮断すると、ネットワークAからのメンテやサーバの参照ができないので新規接続セッションのみ遮断することとします。(もっときれいな方法があるのかもしれませんが、これくらいしか思いつきませんでした。)
最終的に作成した iptables の設定用シェルスクリプトは下記のような感じとなりました。
このシェルスクリプトを走らせて、#service iptables save , #service iptables restart とすれば設定が適用されます。
#!/bin/sh
# Router Version
trusthost='192.168.0.0/24'
myhost='192.168.0.10'
any='0.0.0.0/0'
internal_ip='192.168.1.0/24'
my_internal_host='192.168.1.1'
my_nat_ip='192.168.0.11'
echo 1 > /proc/sys/net/ipv4/ip_forward
##############
#Flush & Reset
##############
iptables -F
iptables -t nat -F
iptables -X
##############
#Deafult Rule
##############
#########################
#フォワーディングのルール
#########################
iptables -A FORWARD -i eth1 -o eth0 -p tcp -m state --state NEW -s $any -d $trusthost -j DROP
iptables -A FORWARD -i eth1 -o eth0 -s $internal_ip -j ACCEPT
iptables -A FORWARD -i eth0 -o eth1 -d $internal_ip -j ACCEPT
iptables -A FORWARD -m state --state ESTABLISHED,RELATED -j ACCEPT
#########################
#ルーティングのルール
#########################
iptables -t nat -A POSTROUTING -s 192.168.1.2 -j SNAT --to $my_nat_ip
iptables -t nat -A PREROUTING -d $my_nat_ip -p tcp -j DNAT --to 192.168.1.2
iptables -t nat -A PREROUTING -d $my_nat_ip -p icmp -j DNAT --to 192.168.1.2
#########
#logging
#########
iptables -N LOGGING
iptables -A LOGGING -j LOG --log-level warning --log-prefix "DROP:" -m limit
iptables -A INPUT -j LOGGING
iptables -A OUTPUT -j LOGGING