iptables (netfilter) のインストール

この文書にはあまり自信がありません.致命的なミス,改善点に気がついた方は,連絡をくれると非常に嬉しいです.

iptables とは kernel の netfilter を制御するユーザ空間のコマンドです.これによりマシンにパケットフィルタリングを可能にします. netfilter を有効にするには,Linux Kernel の CONFIG_NETFILTER とそのオプションである CONFIG_IP_NF_*** をカーネルに組み込むかモジュールにしておく必要があります. Vine Linux の Linux Kernel ではすでにこれらは有効でモジュールの形で実装されています.このサーバのカーネルではモジュールのロードをさせるのが面倒なので,すべてカーネルに組み込んでいます.

iptables のインストールは簡単で,Vine であれば apt-get install iptables とするだけで完了です.

iptables の簡単な説明

iptables は下のような流れでパケットをさばきます.
iptables.png
まず入ってきたパケットは PRETOUNTING チェインで Linux Machine を通過する(中継する)パケットかどうかを調べます.通過するパケットなら FORWARD チェインに, Linux Machine に入ってくるパケットなら,INPUT チェインに振り分けられます.Linux Machine から出てゆくパケットは OUTPUT チェインを通り POSTROUTING チェインへ, FORWARD を通過したパケットはそのまま POSTROUTING チェインに入って外へ出てゆきます.これら通過中におけるチェインに条件を設け,その条件にマッチしたものをターゲットに適用することでパケットを制御します.ここで言うターゲットとは,特別なターゲットであるACCEPT,DROP,QUEUE,RETRUN やユーザ定義のチェインの名前です.ACCEPT は許可でありパケットを通過させ,DROP は落とす個でありパケットを落とし(REJECT 破棄とは若干異なる ),QUEUE は割り込みでありパケットをユーザー空間に渡し,RETURN はチェインの検討を中止し,元のチェインでの評価を行います.組込み済みチェインで RETURN ターゲットにパケットが入った場合そのチェインのデフォルトポリシーにゆだねられます. 複数の NIC が装着されているマシンでは両方についてこのチェインが適用されます. *本当は Linux Machine より Local Process のほうが適当ですが,わかりやすくこうしました.

iptables には nat,filter,mangle の3つのテーブルがあり,その中にそれぞれチェインを持っています.それぞれのチェインが持つテーブルは以下の通りです.

nat PREROUTING OUTPUT POSTROUTING
filter INPUT FORWARD OUTPUT
mangle PREROUTING OUTPUT

mangle はパケットをユーザ空間に渡すチェインでほぼ使用しないのでここでは触れません,よく見ると nat と filter の両方に OUTPUT が あるのがわかります,man コマンドでこれらの差を見てみると nat の OUTPUT には "for altering locally-generated packets before routing : ルーティング前の変更するローカルプロセス由来のパケットに適用", filter の OUTPUT には "for locally-generated packets : ローカルプロセス由来のパケットに適用" となっています.すなわち,nat の OUTPUT チェインはパケットを何か変化させるもので,filter の OUTPUT はパケットをフィルタする ということです.通常では nat の OUTPUT はほぼ使わないでしょう.

フィルタリングの設定

次にフィルタリングの決定します.その前にパケットをどうしたいかまとめておきます.また,各チェインにはデフォルトポリシーというものがあり, チェインのルールから漏れたもに適用されます.例えばデフォルトポリシーを ACCEPT にすれば,ルールから漏れたパケットはすべて許可され, DROP にすれば,ルールから漏れたパケットはすべて落とされます.すなわち,許可すべきものが落とすべきものより多いときはデフォルトポリシーを ACCEPT に,落とすべきものが許可すべきものより多いときはデフォルトポリシーを DROP にするということです.外界に接続のあるマシンでは大抵 落とすべきものが多いのでここではデフォルトを DROP として考えます.当サーバで考えられる許可すべきものをまとめると以下の通りです

  1. LAN 内から Linux マシンを通過するパケットはすべて許可
  2. LAN 内から Linux マシンへのパケットはすべて許可
  3. Linux マシンから LAN 内へのパケットはすべて許可
  4. 外界から Linux マシンへのパケットは HTTP のみ許可
  5. Linux マシンからでゆくパケットで許可するものは FTP,HTTP,NTP
  6. Squid が透過 HTTP プロキシに必要なパケットを許可
  7. Frox が透過 FTP プロキシに必要なパケットを許可
  8. DNS は LAN 内で使用

まず何よりも大事なのはローカルループバックデバイス(lo)を許可することです.これはマシン内で通信をするときに使用されるデバイスで, lo へのパケットの流れはすべて許可しなくてはなりません.

 
# iptables -t filter -A INPUT -i lo -j ACCEPT
# iptables -t filter -A OUTPUT -o lo -j ACCEPT

1から順を追って設定してみましょう.iptables コマンドの使用法は, Manage of IPTABLES に譲るとして,1 を出来るようにするには FORWARD チェインに LAN 内のパケットを許可するようにすればいいと思いますが それだけではうまく LAN 内から外界へ接続はできません.なぜなら LAN 内のパケットはプライベート IP なので外界とは通信できません. そこで LAN から外界に出るパケットの IP をグローバル IP(Linux マシンの IP)に変換する必要があります.またフォワーディングをカーネルに 伝える必要があります.

 
カーネルにフォワーディングを伝える
# echo 1 > /proc/sys/net/ipv4/ip_forward
Vine の場合次回起動時にもこの設定を有効にするには
/etc/sysctl.conf で net.ipv4.ip_forward = 1 としておきます
LAN 内の IP をグローバル IP(Linux マシンの IP)に変換
ここで LOCAL_NET というのは LAN 内の IP(192.168.0.0/24 とか 172.16.0.0/24)を指します
また OUT_IF というのは外界に向いているほうの NIC(eth0 とか eth1)を指します
# iptables -t nat -A POSTROUTING  -s LOCAL_NET -o OUT_IF -j MASQUERADE
フォワーディングを許可します
# iptables -t filter -A FORWARD -s LOCAL_NET -j ACCEPT
# iptables -t filter -A FORWARD -d LOCAL_NET -j ACCEPT

次に 2 と 3 を出来るようにします.

 
ここで,IN_IF というのは LAN 内に向いているほうの NIC (eth0 とか eth1)を指します
# iptables -t filter -A INPUT -i IN_IF -s LOCAL_NET -j ACCEPT
# iptables -t filter -A OUTPUT -o IN_IF -d LOCAL_NET -j ACCEPT

次に 4 を出来るようにします.ただし,HTTPD の使用するポートを開放するだけではセキュリティーが少し弱いので少し工夫をします. 通常 TCP/IP では下のような3ハンドシェイク方式で通信をします.
TCP-IP.png
上の図のように接続が確立されると,お互い自由にパケットを送信できるようになります.そしてそのときは ACK フラグが立っています. Client からのパケットはすべて許可をするとしましょう.Server から出てゆくパケットは接続が確立(ESTABLISHED)されかつ,SYN+ACK と ACK フラグが立っているパケットのみを許可します.なぜこのようなことをするかというと,万が一 HTTPD がのっとられたりしたとき,怪しいフラグのたっている パケットを阻止するのが目的です.通常 HTTPD は自ら他のホストへ接続することはありません. ですから,新しい接続を要求する SYN のみが立っているパケットを阻止する必要があります.

 
# iptables -t filter -A INPUT -p tcp -i OUT_IF --dport 80 -j ACCEPT
# iptables -t filter -A OUTPUT -p tcp -o OUT_IF --sport 80 -m state --state ESTABLISHED ! --syn -j ACCEPT

次に 5 を出来るようにします.

 
FTP の設定 
# iptables -t filter -A INPUT -i OUT_IF -p tcp --sport 21 -j ACCEPT
# iptables -t filter -A INPUT -i OUT_IF -p -tcp --dport 1024:65535 \
-m state --state RELATED,ESTABLISHED -j ACCEPT
# iptables -t filter -A OUTPUT -o OUT_IF -p tcp --dport 21 -j ACCEPT
# iptables -t filter -A OUTPUT -o OUT_IF -p tcp --sport 1024:65535 \
-m state --state NEW,RELATED,ESTABLISHED -j ACCEPT
HTTPD の設定
# iptables -t filter -A OUTPUT -o OUT_IF -p tcp --dport 80 -j ACCEPT
# iptables -t filter -A INPUT -i OUT_IF -p -tcp \
-m state --state NEW,RELATED,ESTABLISHED --sport 80 -j ACCEPT
NTP の設定
# iptables -t filter -A INPUT -p udp -i OUT_IF --dport 123 -j ACCEPT
# iptables -t filter -A OUTPUT -p udp -o OUT_IF --sport 123 -j ACCEPT

次に 6,7 を出来るようにします.

 
# iptables -t nat -A PREROUTING -p tcp -s LOCAL_NET --dport 80 -j REDIRECT --to 3128
# iptables -t nat -A PREROUTING -p tcp -s LOCAL_NET --dport 21 -j REDIRECT --to 2121

次に 8 を出来るようにします.内向き DNS ですから,外からの要求は無視して LAN 内からの要求のみを許可します.

 
# iptables -t filter -A INPUT -i OUT_IF -p udp --sport 53 -j ACCEPT
# iptables -t filter -A OUTPUT -o OUT_IF -p udp --dport 53 -j ACCEPT

最後にデフォルトポリシーを DROP にします.

 
# iptables -t filter -P INPUT DROP
# iptables -t filter -P FORWARD DROP
# iptables -t filter -P OUTPUT DROP

次回起動時にも同じルールが構成されるようにテーブルの内容を保存します.

 
保存先のファイルはディストリビューションによって異なるかもしれません
# iptables-save > /etc/sysconfig/iptables

これで大体の設定は完了ですが,これですべてではありません,まだまだまだまだ甘いです.iptables にはもっと便利な使い方がありこれまだ序の口の序の口です.また,iptables-save によって保存されたファイルは iptables のバージョンによっては使えない場合がありますので,上記の手順をスクリプトなどにして保存しておくほうが安全でしょう.

参考リンク