Kozupon.com    
 
 解りにくいiptablesのアルゴリズム!


iptablesは、Kernel2.4からLinuxにマウントされたフィルタリングモジュールである。Kernel2.2の時には、ipchainsと言うフィルタリングモジュールで有った。しかし、いずれにしても両者ともカーネルに包括されたモジュールなので単独モジュールではない。つまり、使用するしないはカーネルのコンパイル時点で使う旨の設定をしないと使えない。正直、俺はまともにipchainsやiptablesを使ってきたが未だにこんなわかりずらい機能は無い(;o;)。
ipchainsとiptablesは似通ってると思うだろうが、両者全然異質の物だ!記述方法、コマンドは似ているがアルゴリズムが違う。iptablesに関しては、ネットでも色々な方々が説明や設定サンプルの公開をしているが、みんな考え方がバラバラでどれが本当の設定なのか解らない。さらに、書籍も殆ど無いのが現状だ。今回は、この解りにくいiptablesを俺なりに説明したいと思う。でも、俺の説明が決して解りやすいとは限らないので悪しからず(笑)。


1.ゲートウェイマシンにおけるチェーンの構成と考え方

図1


図2

図3

上の図を見て頂きたい。これは、ゲートウェイサーバでipchainsのチェーンがどのように使われるか、俺が自己流で書いた図である。俺はどうもこのような簡単な図を書かねばわからない。たまたま、ローカルIPをグローバルIPにマスカレードしてついでにフィルターしちゃおかルータを作ろうと考えたのでついでにiptablesについて深く考察してみたと言うわけである。したがって、俺の場合は図1のローカルサーバを外部公開しない場合のチェーンでiptablesを仕込んだ。

■ 図1は、ローカル側もしくはグローバル側DMZとしてサーバが別にあり、ゲートウェイは単なるルータとして機能してる場合を示す。
■ 図2は、ゲートウェイがルータとしての役目だけではなく、サーバとしても機能してる場合を示す。
■ 図3は、iptablesのチェーン別のパケットの流れをまとめてみた。

図1、図2は、共に左側がLocal側、右側がGlobal側である。グローバル側からゲートウェイサーバへのアクセスはこれの逆で考えればよい。

1) 単なるルータとして構築するゲートウェイサーバ

図1は、PREROUTING、FORWARD、POSTROUTINGで構成される。PREROUTINGチェーンは、NAPT(アドレス→ポート変換)を使ってLocalサーバをGlobalへ公開するときに使うパラメータである。FORWARDチェーンはその名の通り転送するパラメータである。POSTROUTINGは、IPMASQUEARADEするときに使うパラメータである、ご存じの通り複数のローカルIPのホストをグローバルIPに変換するものである。

@ ローカルサーバをルータ経由でグローバル公開する場合

PREROUTINGチェーンを使ってローカルサーバのIPアドレスと公開するサービスのポート番号をiptablesコマンドで設定する。さらに、POSTROUTINGチェーンでIPMASQUERADEしてグローバル公開する。

A ローカルクライアントの単なるルータとして使う場合

FORWARDチェーンでパケットの転送制限を掛けてフィルタリングとする。さらに、POSTROUTINGチェーンでIPMASQUERADEしてローカルIPをグローバルIPに変換して使用する。

2) グローバル公開用のサーバを兼用するルータとして構築するゲートウェイサーバ

図2は、OUTPUT、INPUT、POSTROUTINGで構成される。OUTPUTチェーンは、ローカル→グローバルに出ていくパケットを制限するパラメータである。INPUTチェーンは、グローバル→ローカルに入ってくるパケットを制限する。POSTROUTINGは、IPMASQUEARADEするときに使うパラメータである。あくまでも、OUTPUTチェーン、INPUTチェーンはゲートウェイサーバで動くサーバモジュールの前後に位置してパケットの制限をしている。

@ ゲートウェイサーバ内で動くサーバモジュールをグローバル公開する場合

INPUTチェーンを使ってサーバへのグローバル側からのアクセス制限を行う。OUTPUTチェーンでローカル側からのグローバルへのアクセス制限を行う。さらに、POSTROUTINGチェーンでIPMASQUERADEしてローカルIPをグローバルIPに変換して使用する。

つまり、俺の言いたいことは、ゲートウェイサーバでファイアーウォールとしての機能を考えた場合、フィルタとサーバが兼用のマシンではINPUTチェーン・OUTPUTチェーンでサーバへのフィルタリングを行い、フィルタリングのみのただのルータマシンではFORWARDチェーンでフィルタリングを行う。と言う違いがある事をここでは言いたかった。


2.ローカルクライアントの単なるルータとして使う事例

図4

図4のようなネットワーク構成の事例で斜線部のgw3という単なるルータとしてのファイアーウォールを例とした場合、iptablesの設定は以下のようになる。この構成での本来の目的は、DMZ(公開鯖を設置したい)を作るためにBBルータを使い、gw3でLAN側とWAN側のゲートウェイ兼ファイアーウォールを構成している。この場合のiptablesでは、基本的にはFORWARDチェーンのみで構成できる。

@ フォワードチェーンのみで設定した場合

# vi set_fw.sh

#!/bin/sh

# modules カーネルオプションモジュールセット。
modprobe iptable_nat

# Enable ip forward IPフォワーディング許可。
echo 1 > /proc/sys/net/ipv4/ip_forward

# フィルターチェーン初期化
iptables -F
iptables -t nat -F
iptables -X
iptables -Z

# デフォルトポリシーフォワード拒否
iptables -P FORWARD DROP

# パケットのステートフル性を確認し、「--state ESTABLISHED,RELATED」となっているものに通過許可を与える。
iptables -A FORWARD -m state --state ESTABLISHED,RELATED -j ACCEPT

# ICMPポートへのパケットの通過を許可。
iptables -t filter -A FORWARD -i eth0 -p icmp --icmp-type echo-request -j ACCEPT
iptables -t filter -A FORWARD -i eth0 -p icmp --icmp-type echo-reply -j ACCEPT

# ローカルクライアントは、TCP通信で20〜23、25、53、110、2401、6660〜6667のポートへのパケットの通過を許可。
iptables -A FORWARD -s 192.168.0.0/16 -d 0/0 -p tcp --dport 20:23 -j ACCEPT
iptables -A FORWARD -s 192.168.0.0/16 -d 0/0 -p tcp --dport 25 -j ACCEPT
iptables -A FORWARD -s 192.168.0.0/16 -d 0/0 -p tcp --dport 53 -j ACCEPT
iptables -A FORWARD -s 192.168.0.0/16 -d 0/0 -p tcp --dport 110 -j ACCEPT
iptables -A FORWARD -s 192.168.0.0/16 -d 0/0 -p tcp --dport 2401 -j ACCEPT
iptables -A FORWARD -s 192.168.0.0/16 -d 0/0 -p tcp --dport 6660:6667 -j ACCEPT

# ローカルクライアントは、UDP通信で 53、110、2401、6660〜6667のポートへのパケットの通過を許可。
iptables -A FORWARD -s 192.168.0.0/16 -d 0/0 -p udp --dport 53 -j ACCEPT
iptables -A FORWARD -s 192.168.0.0/16 -d 0/0 -p udp --dport 110 -j ACCEPT
iptables -A FORWARD -s 192.168.0.0/16 -d 0/0 -p udp --dport 2401 -j ACCEPT
iptables -A FORWARD -s 192.168.0.0/16 -d 0/0 -p udp --dport 6660:6667 -j ACCEPT

# ローカルサーバ群はALLパケット通過許可。
iptables -A FORWARD -s 192.168.0.0/28 -d 0/0 -p all -j ACCEPT

# MASQUERADE ACCEPT LAN側からWAN側へマスカレードしながらの転送を許可
iptables -t nat -A POSTROUTING -s 192.168.0.0/16 -o eth1 -j SNAT --to 210.xxx.xxx.xxx
iptables -t nat -A POSTROUTING -s 192.168.0.0/28 -o eth1 -j SNAT --to 210.xxx.xxx.xxx

# FTP & IRC許可

modprobe ip_nat_ftp
modprobe ip_nat_irc
modprobe ip_conntrack_ftp
modprobe ip_conntrack_irc

# 設定状態確認(nat & filter)
iptables -t nat -L -n
iptables -t filter -L -n

# ルーティング設定
route add -net 192.168.10.0 netmask 255.255.255.0 gateway 192.168.0.34 eth0
route add -net 192.168.3.0 netmask 255.255.255.0 gateway 192.168.0.25 eth0
route add -net 192.168.5.0 netmask 255.255.255.0 gateway 192.168.0.26 eth0
route add -net 192.168.7.0 netmask 255.255.255.0 gateway 192.168.0.27 eth0

# mtu値設定
ifconfig eth1 mtu 1454

A インプットチェーンを加えてセキュリティ効果を高くした設定(通常@で良いが、あえてINPUTチェーンを設定してセキュアーにしている)

#!/bin/sh

# モジュールセット、iptable_nat
modprobe iptable_nat

# ipフォワーディングイネーブル
echo 1 > /proc/sys/net/ipv4/ip_forward

# nat & filter & policy 全て初期化
iptables -F
iptables -t nat -F
iptables -X
iptables -Z

# セットデフォルトポリシー
# INPUTチェーン全て拒否

iptables -P INPUT DROP
# FORWARDチェーン全て拒否
iptables -P FORWARD DROP
# OUTPUTチェーン全て許可
iptables -P OUTPUT ACCEPT

# セッティングipマスカレード
iptables -t nat -A POSTROUTING -o eth1 -j MASQUERADE
# iptables -t nat -A POSTROUTING -o eth1 -j SNAT --to 61.xxx.xxx.xxx

# 全てのレスポンスパケット許可
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
iptables -A FORWARD -m state --state ESTABLISHED,RELATED -j ACCEPT

# 指定TCPポート許可

# pingポートINPUTチェーンicmp許可
iptables -A INPUT -i eth1 -p icmp -j ACCEPT
# eth0からのicmp通過許可
iptables -A FORWARD -i eth0 -p icmp -j ACCEPT

# INPUTチェーン20番ポート許可(WAN→LAN)
iptables -A INPUT -i eth1 -p tcp --dport 20 -j ACCEPT
# 192.168.0.0/16から20番ポートアクセスパケット通過許可(LAN→WAN)
iptable -A FORWARD -s 192.168.0.0/16 -p tcp --dport 20 -j ACCEPT

# INPUTチェーン21番ポート許可(WAN→LAN)
iptables -A INPUT -i eth1 -p tcp --dport 21 -j ACCEPT
# 192.168.0.0/16から21番ポートアクセスパケット通過許可(LAN→WAN)
iptables -A FORWARD -s 192.168.0.0/16 -p tcp --dport 21 -j ACCEPT

# INPUTチェーン22番ポート許可(WAN→LAN)
iptables -A INPUT -i eth1 -p tcp --dport 22 -j
ACCEPT
# 192.168.0.0/16から22番ポートアクセスパケット通過許可(LAN→WAN)
iptables -A FORWARD -s 192.168.0.0/16 -p tcp --dport 22 -j ACCEPT

# INPUTチェーン23番ポート許可(WAN→LAN)
iptables -A INPUT -i eth1 -p tcp --dport 23 -j ACCEPT
# 192.168.0.0/16から23番ポートアクセスパケット通過許可(LAN→WAN)
iptables -A FORWARD -s 192.168.0.0/16 -p tcp --dport 23 -j ACCEPT

# INPUTチェーン25番ポート許可(WAN→LAN)
iptables -A INPUT -i eth1 -p tcp --dport 25 -j ACCEPT
# 192.168.0.0/16から25番ポートアクセスパケット通過許可(LAN→WAN)
iptables -A FORWARD -s 192.168.0.0/16 -p tcp --dport 25 -j ACCEPT

# INPUTチェーン53番ポート許可(WAN→LAN)
iptables -A INPUT -i eth1 -p tcp --dport 53 -j ACCEPT
# 192.168.0.0/16から53番ポートアクセスパケット通過許可(LAN→WAN)
iptables -A FORWARD -s 192.168.0.0/16 -p tcp --dport 53 -j ACCEPT

# INPUTチェーン110番ポート許可(WAN→LAN)
iptables -A INPUT -i eth1 -p tcp --dport 110 -j ACCEPT
# 192.168.0.0/16から110番ポートアクセスパケット通過許可(LAN→WAN)
iptables -A FORWARD -s 192.168.0.0/16 -p tcp --dport 110 -j ACCEPT

# INPUTチェーン587番ポート許可(WAN→LAN)
iptables -A INPUT -i eth1 -p tcp --dport 587 -j ACCEPT
# 192.168.0.0/16から587番ポートアクセスパケット通過許可(LAN→WAN)
iptables -A FORWARD -s 192.168.0.0/16 -p tcp --dport 587 -j ACCEPT

# INPUTチェーン995番ポート許可(WAN→LAN)
iptables -A INPUT -i eth1 -p tcp --dport 995 -j ACCEPT
# 192.168.0.0/16から995番ポートアクセスパケット通過許可(LAN→WAN)
iptables -A FORWARD -s 192.168.0.0/16 -p tcp --dport 995 -j ACCEPT

# INPUTチェーン2401番ポート許可(WAN→LAN)
iptables -A INPUT -i eth1 -p tcp --dport 2401 -j ACCEPT
# 192.168.0.0/16から2401番ポートアクセスパケット通過許可(LAN→WAN)
iptables -A FORWARD -s 192.168.0.0/16 -p tcp --dport 2401 -j ACCEPT

# 指定UDPポート許可

# INPUTチェーン53番ポート許可(WAN→LAN)
iptables -A INPUT -i eth1 -p udp --dport 53 -j ACCEPT
# 192.168.0.0/16から53番ポートアクセスパケット通過許可(LAN→WAN)
iptables -A FORWARD -s 192.168.0.0/16 -p udp --dport 53 -j ACCEPT

# INPUTチェーン110番ポート許可(WAN→LAN)
iptables -A INPUT -i eth1 -p udp --dport 110 -j ACCEPT
# 192.168.0.0/16から110番ポートアクセスパケット通過許可(LAN→WAN)
iptables -A FORWARD -s 192.168.0.0/16 -p udp --dport 110 -j ACCEPT

# INPUTチェーン995番ポート許可(WAN→LAN)
iptables -A INPUT -i eth1 -p udp --dport 995 -j ACCEPT
# 192.168.0.0/16から995番ポートアクセスパケット通過許可(LAN→WAN)
iptables -A FORWARD -s 192.168.0.0/16 -p udp --dport 995 -j ACCEPT

# 192.168.0.0/28からの全てのパケットを通過許可(LAN→WAN)
iptables -A FORWARD -s 192.168.0.0/28 -p all -j ACCEPT

# INPUTチェーンのみlogを採る
iptables -A INPUT -j LOG --log-prefix "IPTABLES_LOG : " --log-level=info

# 各種ローディングモジュールセッティング
modprobe ip_nat_ftp
modprobe ip_nat_irc
modprobe ip_conntrack_ftp
modprobe ip_conntrack_irc

# ここでセッティングしたチェーンをビューする
iptables -t nat -L -n
iptables -t filter -L -n

# 各ルーティングテーブルセッティング
route add -net 192.168.0.0 netmask 255.255.255.0 gateway 192.168.0.1 eth0
route add -net 192.168.10.0 netmask 255.255.255.0 gateway 192.168.0.34 eth0
route add -net 192.168.3.0 netmask 255.255.255.0 gateway 192.168.0.25 eth0
route add -net 192.168.5.0 netmask 255.255.255.0 gateway 192.168.0.26 eth0
route add -net 192.168.7.0 netmask 255.255.255.0 gateway 192.168.0.27 eth0

# mtuセッティング
ifconfig eth1 mtu 1454


3.iptablesログをとる

設定ファイルで、赤字の部分はiptablesログを採る為に設定する部分だ。iptablesでは、特にDROPするチェーンにログを採取を仕掛けておくと、何かと都合がいいです。
-j LOG でログ出力を指定して、 --log-prefix "IPTABLES_LOG : "で出力されたログの行頭に追加される文字列を指定する。
さらに、--log-level=infoでinfoレベルのログを出力する(指定しないでデフォルトだとカーネルログに出力される)。

1)syslogへの設定
syslogに対しての設定を以下に示す。

/etc/syslog.conf へ以下の行を追加する。

kern.info                  /var/log/iptables.log

その後、syslogdをリスタートする。

2)ログローテーションの設定

/etc/logrotate.d/syslog ファイルに、 /var/log/iptables.log を追加する。


4.その他考察

こう説明されても解らないものは解らない。と言う理論も成り立つ、現に俺は何でこんなめんどくさい事をしなければならないのかという事も当初思った。
しかしならが、ipchainsでせっかく設定したフィルタリングポリシーをiptablesに置き換えるのにどうしても抵抗がある方は、iptablesをipchainsにエミュレートしてくれるカーネルモジュールがある。

modprobe ipchains

をポリシーファイルの先頭で定義しておけば、ipchainsの定義をiptablesに直して動くらしい。残念ながら俺は試してない。なぜなら、中でマスカレード定義がアバウトらしいから「なんちゃってiptables」という言葉が当てはまりそうだ(;-_-;)
だから、完璧をきしたい諸君はiptablesを学んだ方が得策のように思える。
さらに、iptablesは参考になるサイトの正当性が評価しにくい。したがって、自分なりに定義して動作させたときは必ず動作確認とちゃんとフィルタリングが掛かってるかどうかの評価を確実に行って欲しい。

以上

 


 
 
 



Copyright 2009 Kozupon.com.