[[PageOutline]] = iptables = * http://www.designandcommunication.co.jp/Security/iptables/ * テーブル、チェインなどの基礎知識 * [http://www.atmarkit.co.jp/flinux/rensai/security04/security04a.html Linuxで作るファイアウォール[NAT設定編](1/2)] * [http://www.atmarkit.co.jp/flinux/rensai/security05/security05a.html Linuxで作るファイアウォール[パケットフィルタリング設定編](1/2)] * see also [http://www.atmarkit.co.jp/flinux/index/indexfiles/securityindex.html 連載記事 「ゼロから始めるLinuxセキュリティ」] * [http://www.designandcommunication.co.jp/Security/iptables/diagram.html Kernel Paket Diagram] * 経路を視覚化したもの (origin => http://www.docum.org/docum.org/kptd/) * [http://hp.vector.co.jp/authors/VA027424/iptables-m.htm iptables拡張] * 応用例 * [http://www.atmarkit.co.jp/flinux/index/indexfiles/iptablesindex.html 連載記事 「習うより慣れろ! iptablesテンプレート集」] * [http://juno106.seesaa.net/article/19373697.html junoのへたれサーバ管理日記: iptablesのログをとる] * デフォルトでは「kern.=warning」で振り分けが出来る {{{ Jul 4 01:54:03 ubuntu-napt kernel: [118136.424992] [UFW BLOCK FORWARD]: IN=eth0 OUT=eth2 SRC=192.168.100.197 DST=130.xyz.68.26 LEN=58 TOS=0x00 PREC=0x00 TTL=63 ID=3740 DF PROTO=UDP SPT=40966 DPT=53 LEN=38 }}} * iptable側では「--log-level err」などとしてpriorityを変更できる * kern.=warningには他にも様々なログが来るので、なるべく混ざらないようにしたければ「kern.=notice」「kern.=err」あたりが妥当か。 * /etc/syslog.conf {{{ kern.=warn -/var/log/kern.warn.log kern.=err -/var/log/kern.err.log }}} * (少なくともUbuntuでは)errに設定するとコンソールにも出力されるので注意 = 設定ファイル = #conffile * Ubuntu => [../ufw] * CentOS * /etc/sysconfig/iptables {{{ # Firewall configuration written by system-config-securitylevel # Manual customization of this file is not recommended. *filter :INPUT ACCEPT [0:0] :FORWARD ACCEPT [0:0] :OUTPUT ACCEPT [0:0] :RH-Firewall-1-INPUT - [0:0] -A INPUT -j RH-Firewall-1-INPUT -A FORWARD -j RH-Firewall-1-INPUT -A RH-Firewall-1-INPUT -i lo -j ACCEPT -A RH-Firewall-1-INPUT -p icmp --icmp-type any -j ACCEPT -A RH-Firewall-1-INPUT -p 50 -j ACCEPT -A RH-Firewall-1-INPUT -p 51 -j ACCEPT -A RH-Firewall-1-INPUT -p udp --dport 5353 -d 224.0.0.251 -j ACCEPT -A RH-Firewall-1-INPUT -p udp -m udp --dport 631 -j ACCEPT -A RH-Firewall-1-INPUT -p tcp -m tcp --dport 631 -j ACCEPT -A RH-Firewall-1-INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT -A RH-Firewall-1-INPUT -m state --state NEW -m tcp -p tcp --dport 22 -j ACCEPT -A RH-Firewall-1-INPUT -j REJECT --reject-with icmp-host-prohibited COMMIT }}} * sshのみListen可 = table = == raw == * http://www.designandcommunication.co.jp/Security/iptables/modules/Modules0.html#raw raw テーブルはiptablesで最初に評価される PREROUTING と OUTPUT で使用出来る rawテーブルはNOTRACKを使用する事でconntrack、NATを適用せずに通過させる その分、高速になる、TRACE でトレース出来る また conntrackやstateモジュールは使用出来ない iptablesで最初に評価されるので、QUEUEやIMQなどにパケットを転送する前に おかしなパケットを廃棄出来る * PREROUTINGが使えることにより、INPUT/FORWARD双方に回る予定のパケットを前もって制御できる * POSTROUTINGもあれば良いのだが… === 巨大 icmp packet の拒否 === #toolargeicmp * デフォルト * ping 202.12.27.33 -c 1 {{{ PING 202.12.27.33 (202.12.27.33) 56(84) bytes of data. 64 bytes from 202.12.27.33: icmp_seq=1 ttl=241 time=5.95 ms }}} * ping 202.12.27.33 -c 1 -s 10240 {{{ PING 202.12.27.33 (202.12.27.33) 10240(10268) bytes of data. 10248 bytes from 202.12.27.33: icmp_seq=1 ttl=241 time=13.3 ms }}} * 自ホストから外へのlarge packetの拒否 * sudo iptables -t raw -A OUTPUT -p icmp --icmp-type echo-request -m length --length 85: -j DROP * ping 202.12.27.33 -c 1 {{{ PING 202.12.27.33 (202.12.27.33) 56(84) bytes of data. 64 bytes from 202.12.27.33: icmp_seq=1 ttl=241 time=10.5 ms }}} * ping 202.12.27.33 -c 1 -s 57 {{{ PING 202.12.27.33 (202.12.27.33) 57(85) bytes of data. ping: sendmsg: Operation not permitted }}} * 着信拒否 * sudo iptables -t raw -A PREROUTING -p icmp --icmp-type echo-request -m length --length 85: -j DROP * via http://www.designandcommunication.co.jp/Security/iptables/modules/Modules0.html#raw * ログを取る場合 {{{ sudo iptables -t raw -A PREROUTING -p icmp --icmp-type echo-request -m length --length 85: -j LOG --log-prefix "[IPTABLES BAD-ICMP]: " --log-level err -m limit --limit 3/min --limit-burst 10 sudo iptables -t raw -A PREROUTING -p icmp --icmp-type echo-request -m length --length 85: -j DROP }}} * 「-m limit」について => パケットサイズが異常なicmp requestが一分間に10回を超えた場合は、一分間に3回のみログを取るように制限する * 無いと膨大なログになる可能性がある == mangle == * どのようなときに使うべきなのかよく分からない。調査中。 * INPUT, OUTPUT, FORWARD, PREROUTING, POSTROUTING の全てのchainが使える = misc = * interfacesのpost-upコマンドでスクリプトを呼び出してiptablesを設定するという手法も考えられる(この場合、ipコマンド等を使ってIP/Netmask等を取得できるので、スクリプト中にWANやLANのアドレスを埋め込まなくて良いという利点が考えられる)が、その場合NICが活性化してからiptablesの設定がされることになり、瞬間的にではあるがLinkUPしたにも関わらずFWが未設定という状態になるのでよろしくないと思われる。 * eth0がLAN側で192.168.100.254/24、eth1~ethNがWAN(マルチホーム等)の時、条件の逆転「!」を使うことで、iptablesのルール数を減らすべく、以下のようにIP Spoofing防御設定まとめられる思えるが、実際には問題がある。 {{{ sudo iptables -t raw -N LOG_SPOOF sudo iptables -t raw -A LOG_SPOOF -j LOG --log-prefix "[IP-SPOOFING]: " sudo iptables -t raw -A LOG_SPOOF -j DROP sudo iptables -t raw -A PREROUTING -i ! lo -s 127.0.0.0/8 -j LOG_SPOOF sudo iptables -t raw -A PREROUTING -i ! eth0 -s 10.0.0.0/8 -j LOG_SPOOF sudo iptables -t raw -A PREROUTING -i ! eth0 -s 172.16.0.0/12 -j LOG_SPOOF sudo iptables -t raw -A PREROUTING -i ! eth0 -s 192.168.0.0/16 -j LOG_SPOOF }}} * ping 192.168.100.254 (=eth0)が通らない {{{ Jul 4 07:07:28 ubuntu-napt kernel: [136737.367943] [IP-SPOOFING]: IN=lo OUT= MAC=00:00:00:00:00:00:00:00:00:00:00:00:08:00 SRC=192.168.100.254 DST=192.168.100.254 LEN=84 TOS=0x00 PREC=0x00 TTL=64 ID=0 DF PROTO=ICMP TYPE=8 CODE=0 ID=40230 SEQ=1 Jul 4 07:07:29 ubuntu-napt kernel: [136738.366434] [IP-SPOOFING]: IN=lo OUT= MAC=00:00:00:00:00:00:00:00:00:00:00:00:08:00 SRC=192.168.100.254 DST=192.168.100.254 LEN=84 TOS=0x00 PREC=0x00 TTL=64 ID=0 DF PROTO=ICMP TYPE=8 CODE=0 ID=40230 SEQ=2 }}} * 「IN=lo」となっていることから考えると、192.168.100.254=eth0だが実際にはloopbackに送られているためおかしくなる。 * WANの数だけルールを列挙するしかなさそう? * filter table以外を/etc/ufw/*.rulesに書くと、ufw startで反映はされるがufw stopで消去されないので設定が累積していく * ~~interfaces pre-upとかに入れるのがよさそう…~~ => スクリプトを作成 => [#setfilter] = sample script = * source:/trunk/iptables == [source:/trunk/iptables/setnapt.sh setnapt.sh] == * for Ubuntu * nat table(のPOSTROUTINGチェイン)を添削するため、[#setfilter]の[13]以降と排他利用 * source:/trunk/iptables/setfilter@10 とは共用可能 * WANデバイス毎にIP MASQUERADEを設定 * /etc/network/interfaces にて、LANデバイスの活性化時に自動呼び出しされるようにして使用 {{{ auto eth0 iface eth0 inet static address 192.168.100.254 netmask 255.255.255.0 post-up /root/setnapt.sh eth1 eth2 post-down /root/setnapt.sh }}} * 上の例ではWANはeth1,2ということになる == [source:/trunk/iptables/setfilter setfilter] == * for Ubuntu * raw, mangle nar tableを使って不要・異常なパケットを落とすポリシーを起動時自動登録 * natテーブルをresetするため、[#setnapt.sh]と排他利用 * /etc/init.d/setfilter start/stop * source:/trunk/iptables/ufw と併せて使用 * sudo update-rc.d setfilter start 39 S . * /etc/rcS.d/S39setfilter -> ../init.d/setfilter == [source:/trunk/iptables/ufw ufw/] == * for Ubuntu * /etc/ufw/*.rules に配置 === [12] === * LANがeth0, WANがeth1という想定 * LAN => 192.168.100.0/24 * IP MASQUERADEについては[#setnapt.sh]で設定 * LAN -> GW ->WAN の通信は通過 * WAN -> GW は拒否 * after.rules, before.rules については既存のルールに追加 * ログは「「--log-level err」にしているが、Ubuntuではコンソールにも出力されるようになるので注意 (コンソールで作業する際に表示が邪魔になる) * noticeあたりにすればコンソール出力は無くなる === [13] === * 22/tcp, 443/tcpをWANからもListen可能に。 * REDIRECTを用いて、 * 同じポートだがNICごとに違うサービスに接続できる 1. 8443/tcpへ届いたパケットは443/tcpへ転送(全NIC) 1. WAN(eth1)側のみ、8000/tcp -> 443/tcp と転送 1. LAN(eth0)側のみ、8000/tcp -> 22/tcp と転送 * REDIRECTする場合は、転送先ポートでのINPUTがACCEPTされている必要がある * REDIRECTのみ設定し、[changeset:13#file1 INPUT chain]側は設定しない(つまり8443/tcp, 8000/tcpのみListenしたい)のは不可 * DNATを用いて、loopback等必ずACCEPTされるデバイスに転送する方法が使えるかも(未検証) see also [http://www.atmarkit.co.jp/flinux/rensai/iptables02/iptables02d.html @IT:natテーブルを利用したLinuxルータの作成(4/6)]