[[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.asahi-net.or.jp/~AA4T-NNGK/ipttut/ Stray Penguin - Linux Memo (Iptables tutorial)] * 応用例 * [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の数だけルールを列挙するしかなさそう? * ルールを削除する際は、追加するときの-Aをそのまま-Dに変えればよい * ルール追加 => sudo iptables -t nat -A PREROUTING -i eth0 -s ! 192.168.100.254 -d 133.xy.zz.39 -j DNAT --to-destination 192.168.100.254 * 上記ルールを削除するときは↓ * ルール削除 => sudo iptables -t nat -D PREROUTING -i eth0 -s ! 192.168.100.254 -d 133.xy.zz.39 -j DNAT --to-destination 192.168.100.254 = sample script = * source:/trunk/TipAndDoc/iptables * 注意 * /etc/init.d/ufw (see [../ufw#etcinit.dufw]) でiptablesのfilterテーブルはflushされるため、他のスクリプトでfilterテーブルを追加していても削除されてしまう。 * => ufwスクリプトを先に起動する必要がある * [#setfilter] raw,mangle,natテーブルをflushするため、ufwスクリプトと同様の注意が必要 == ~~[source:/trunk/TipAndDoc/iptables/setnapt.sh setnapt.sh]~~ == * replaced to [#setmasq.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/TipAndDoc/iptables/setfilter setfilter] == * for Ubuntu * raw, mangle nar tableを使って不要・異常なパケットを落とすポリシーを起動時自動登録 * natテーブルをresetするため、[#setnapt.sh]と排他利用 * /etc/init.d/setfilter start/stop * source:/trunk/TipAndDoc/iptables/ufw と併せて使用 * sudo update-rc.d setfilter start 39 S . * /etc/rcS.d/S39setfilter -> ../init.d/setfilter == [source:/trunk/TipAndDoc/iptables/setmasq.sh setmasq.sh] == * for Ubuntu * WAN deviceに対してIP MASQUERADEを設定 * /etc/init.d/networking restart 等で試すと正常に動作するが、OS起動時のrcS.dからの呼び出し時は正常に動作しないことがあるため、[#setfilter]を使って/etc/ufw/nat.rules等で静的に設定する方が良い * ex) /etc/network/interfaces {{{ auto eth1 iface eth1 inet dhcp post-up /root/setroute.sh post-up /root/setlan2wan.sh eth0 post-up /root/setmasq.sh pre-down /root/setlan2wan.sh eth0 post-down /root/setroute.sh post-down /root/setmasq.sh }}} == [source:/trunk/TipAndDoc/iptables/setlan2wan.sh setlan2wan.sh] == * #4への対処をするスクリプト * 設定例は[#setmasq.sh]を参照 == [source:/trunk/TipAndDoc/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を用いて、 1. 8443/tcpへ届いたパケットは443/tcpへ転送(全NIC) 1. WAN(eth1)側のみ、8000/tcp -> 443/tcp と転送 1. LAN(eth0)側のみ、8000/tcp -> 22/tcp と転送 * 同じポートだがNICごとに違うサービスに接続できる * WAN:$ telnet 133.xyz.xxx.39 8000 {{{ Trying 133.xyz.xxx.39... Connected to 133.xyz.xxx.39. Escape character is '^]'. GET / 400 Bad Request

Bad Request

Your browser sent a request that this server could not understand.
Reason: You're speaking plain HTTP to an SSL-enabled server port.
Instead use the HTTPS scheme to access this URL, please.

Hint: https://test.mitty.jp/


Apache/2.2.8 (Ubuntu) DAV/2 SVN/1.5.1 mod_ssl/2.2.8 OpenSSL/0.9.8g Server at test Port 443
Connection closed by foreign host. }}} * LAN:% telnet 192.168.100.254 8000 {{{ Trying 192.168.100.254... Connected to 192.168.100.254. Escape character is '^]'. SSH-2.0-OpenSSH_4.7p1 Debian-8ubuntu1.2 Protocol mismatch. Connection closed by foreign host. }}} * REDIRECTする場合は、転送先ポートでのINPUTがACCEPTされている必要がある * REDIRECTのみ設定し、[changeset:13#file1 INPUT chain]側は設定しない(つまり22/tcp,443/tcpはDROPしたまま、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)] === [17] === * [#setmasq.sh]を使うようになったので、nat.rulesからIP MASQUERADEを削除