Debian に iptables を設定
前回から少し間があいてしまったが、sshd と httpd が立っている Debian に対して、必要最低限のアクセスのみを許可するような設定を施したい。ただ iptables で出来る設定はネットワークに関する知識が乏しい自分にはなかなか難しく、手探り状態ながら作業してみる。
方針としてはその辺のサイトの解説でもよくあるようなホワイトリスト方式。ただし作業元の環境は固定IPアドレスは持っていないので、IPによる接続元制限はできない。
念のため netstat で使用中のポート一覧も確認して知らぬ間にサーバが立っていないか確認しておく。
以降のコマンドは全て su で root になった状態で叩いている。
基本的には参考文献の上2つで大体完結するぐらいの内容。下手に変えない方がよかったかも知れない。
ファイアウォール構築(iptables) - Fedoraで自宅サーバー構築
連載記事 「習うより慣れろ! iptablesテンプレート集」
Man page of IPTABLES
D: Software/iptables - Debian GNU/Linux スレッドテンプレ
セキュリティ強化対策(Iptables編)
ルータ・ファイアウォールiptables)/Fedora Core6
・基本的には全部塞いで必要なところだけ開く(内側から外部へのアクセスも全面的には許可しない)
・ループバックインターフェイスで完結する通信だけは全面的に許可する
・各種攻撃からは防御を試みる
・外部の DNS サーバへの問い合わせを許可する
・HTTP、HTTPS、git、あと GMail で何かすることがあれば使う可能性がある 995,993,587,465 は外部への接続を許可する
・sources.list にリポジトリを追加する際に hkp 鍵サーバと通信する必要があるので 11371 番も外部への接続を許可
・外部からHTTPサーバへの接続を許可する
・外部からSSHサーバへの接続を許可する。ただしブルートフォース攻撃は怖いので過剰なアクセスはDROPするように
この他例えば SSH への接続が日本以外だったら蹴るような対策もすべきだが、現状は仮想PCで外部からは一切アクセスできない状態でテストが面倒なのでとりあえず保留にしてある。
あと外部の HTTP サーバなどに接続する際、ポート番号に 8080 などが使われていると接続できないという問題もある。この手の問題はできれば遭遇するたびに甘くしていく方針にしたい。
今回は仮想サーバで直接マシンのコンソールが開けるので簡単にテストが出来て、SSH が塞がれたままになっても問題なく作業が続行できたものの、リモートのサーバとなるとそうも行かない。
その辺に関してはここにいい説明があって、Windows でモニタを設定を変更するときのように「数秒後に元の状態に戻す」というところまでまとめてコマンドを投げておくことでリモートでのテストをしやすくする解説がある。
実際にリモートでしかできないような環境で設定することになったらこれも試してみようと思う。
参考文献のひとつめの URL では例えば LOCALNET を netstat から自動取得したりするようなコードがあるのだが、Firewall を設定するタイミングではまだその辺は上手く取得できないので IP に関しては直書きしておくことにした。
また国別IPリストの取得処理なども含まれているが、この辺はよく見てないものの設定切り替え時に一瞬無防備になっているような気がして怖いのでとりあえず何もしてない(恐らくiptables-save が吐き出すテキストの中の最後に commit があるので、iptables-restore を使って新しい設定に移行できればいいんじゃないか、という気はちょっとする)。
/etc/firewall.sh を実行して、例えば Windows 側で DOS 窓を2つ開いてサーバに対して同時に ping を打ったりして Ping of Death 対策の確認、Putty を何度も開いてブルートフォース攻撃対策の確認をしたりして、行った設定が上手くいっていることが確認できたら実際にこれがマシン起動時に有効になるようにする。
不安が残るもののとりあえずは大丈夫ということにしておこう。
方針としてはその辺のサイトの解説でもよくあるようなホワイトリスト方式。ただし作業元の環境は固定IPアドレスは持っていないので、IPによる接続元制限はできない。
念のため netstat で使用中のポート一覧も確認して知らぬ間にサーバが立っていないか確認しておく。
以降のコマンドは全て su で root になった状態で叩いている。
netstat -anp問題なさそうだったので、/etc/firewall.sh というファイルを新規作成して、vim で内容を作る。
touch /etc/firewall.sh chmod 700 /etc/firewall.sh vim /etc/firewall.sh
#! /bin/sh LOCALNET=192.168.11.0/255.255.255.0 MY_SSHD_CONFIG=/etc/ssh/sshd_config iptables -F iptables -X iptables -P INPUT DROP iptables -P OUTPUT DROP iptables -P FORWARD DROP # Loopback iptables -A INPUT -i lo -j ACCEPT iptables -A OUTPUT -o lo -j ACCEPT # SYN Cookiesを有効にする # ※TCP SYN Flood攻撃対策 sysctl -w net.ipv4.tcp_syncookies=1 > /dev/null sed -i '/net.ipv4.tcp_syncookies/d' /etc/sysctl.conf echo "net.ipv4.tcp_syncookies=1" >> /etc/sysctl.conf # ブロードキャストアドレス宛pingには応答しない # ※Smurf攻撃対策 sysctl -w net.ipv4.icmp_echo_ignore_broadcasts=1 > /dev/null sed -i '/net.ipv4.icmp_echo_ignore_broadcasts/d' /etc/sysctl.conf echo "net.ipv4.icmp_echo_ignore_broadcasts=1" >> /etc/sysctl.conf # ICMP Redirectパケットは拒否 sed -i '/net.ipv4.conf.*.accept_redirects/d' /etc/sysctl.conf for dev in `ls /proc/sys/net/ipv4/conf/` do sysctl -w net.ipv4.conf.$dev.accept_redirects=0 > /dev/null echo "net.ipv4.conf.$dev.accept_redirects=0" >> /etc/sysctl.conf done # Source Routedパケットは拒否 sed -i '/net.ipv4.conf.*.accept_source_route/d' /etc/sysctl.conf for dev in `ls /proc/sys/net/ipv4/conf/` do sysctl -w net.ipv4.conf.$dev.accept_source_route=0 > /dev/null echo "net.ipv4.conf.$dev.accept_source_route=0" >> /etc/sysctl.conf done # フラグメント化されたパケットはログを記録して破棄 iptables -A INPUT -f -j LOG --log-prefix '[IPTABLES FRAGMENT] : ' iptables -A INPUT -f -j DROP # 外部とのNetBIOS関連、Dropbox関連のアクセスはログを記録せずに破棄 # ※不要ログ記録防止 iptables -A INPUT -s ! $LOCALNET -p tcp -m multiport --dports 135,137,138,139,445,17500 -j DROP iptables -A INPUT -s ! $LOCALNET -p udp -m multiport --dports 135,137,138,139,445,17500 -j DROP iptables -A OUTPUT -d ! $LOCALNET -p tcp -m multiport --sports 135,137,138,139,445,17500 -j DROP iptables -A OUTPUT -d ! $LOCALNET -p udp -m multiport --sports 135,137,138,139,445,17500 -j DROP # 1秒間に4回を超えるpingはログを記録して破棄 # ※Ping of Death攻撃対策 iptables -N LOG_PINGDEATH iptables -A LOG_PINGDEATH -m limit --limit 1/s --limit-burst 4 -j ACCEPT iptables -A LOG_PINGDEATH -j LOG --log-prefix '[IPTABLES PINGDEATH] ' iptables -A LOG_PINGDEATH -j DROP iptables -A INPUT -p icmp --icmp-type echo-request -j LOG_PINGDEATH # ポートスキャン対策 iptables -N LOG_PORTSCAN iptables -A LOG_PORTSCAN -m limit --limit 1/s --limit-burst 4 -j RETURN iptables -A LOG_PORTSCAN -j LOG --log-level info --log-prefix '[IPTABLES PORTSCAN] ' iptables -A LOG_PORTSCAN -j DROP iptables -A INPUT -p tcp --tcp-flags SYN,ACK,FIN,RST RST -j LOG_PORTSCAN # 不正パケット対策 iptables -N LOG_NEWSYNCHECK iptables -A LOG_NEWSYNCHECK -j LOG --log-prefix '[IPTABLES NEWSYNCHECK] ' iptables -A LOG_NEWSYNCHECK -j DROP iptables -A INPUT -p tcp ! --syn -m state --state NEW -j LOG_NEWSYNCHECK # 全ホスト(ブロードキャストアドレス、マルチキャストアドレス)宛パケットはログを記録せずに破棄 # ※不要ログ記録防止 iptables -A INPUT -d 255.255.255.255 -j DROP iptables -A INPUT -d 224.0.0.1 -j DROP # 113番ポート(IDENT)へのアクセスには拒否応答 # ※メールサーバ等のレスポンス低下防止 iptables -A INPUT -p tcp --dport 113 -j REJECT --reject-with tcp-reset # 確立に成功した tcp 接続は許可 iptables -A INPUT -p tcp -m state --state ESTABLISHED,RELATED -j ACCEPT iptables -A OUTPUT -p tcp -m state --state ESTABLISHED,RELATED -j ACCEPT # Ping 送受信 iptables -A INPUT -p icmp --icmp-type echo-request -j ACCEPT iptables -A INPUT -p icmp --icmp-type echo-reply -j ACCEPT iptables -A OUTPUT -p icmp --icmp-type echo-request -j ACCEPT iptables -A OUTPUT -p icmp --icmp-type echo-reply -j ACCEPT # DNS 送信 iptables -A INPUT -p udp --sport 53 -j ACCEPT iptables -A OUTPUT -p udp --dport 53 -j ACCEPT iptables -A OUTPUT -p tcp --dport 53 -m state --state NEW -j ACCEPT # HTTP, HTTPS, POP3(SSL), IMAP, SMTP(TLS/STARTTLS, SSL), git, hkp 送信 iptables -A OUTPUT -p tcp -m state --state NEW -m multiport --dports 80,443,995,993,587,465,9418,11371 -j ACCEPT # HTTP 受信 iptables -A INPUT -p tcp -m state --state NEW --dport 80 -j ACCEPT # SSH 受信 / ブルートフォース攻撃対策 # sshd_config ファイルの中からポート番号を指定している箇所を探す SSHD_LISTEN_PORT=`sed -e 's/^Port\s\+\([0-9]\+\)/\1/p' -e d $MY_SSHD_CONFIG` iptables -N LOG_SSHBRUTEFORCE iptables -A LOG_SSHBRUTEFORCE -m limit --limit 3/min --limit-burst 4 -j ACCEPT iptables -A LOG_SSHBRUTEFORCE -j LOG --log-level info --log-prefix '[IPTABLES SSHBRUTEFORCE] ' iptables -A LOG_SSHBRUTEFORCE -j DROP iptables -A INPUT -p tcp -m state --state NEW --dport $SSHD_LISTEN_PORT -j LOG_SSHBRUTEFORCE # 拒否IPアドレスからのアクセスはログを記録せずに破棄 # ※拒否IPアドレスは/root/deny_ipに1行ごとに記述しておくこと # (/root/deny_ipがなければなにもしない) if [ -s /root/deny_ip ]; then for ip in `cat /root/deny_ip` do iptables -I INPUT -s $ip -j DROP done fi # 上記のルールにマッチしなかったアクセスで外部からのものはログを記録(その後自動的に破棄) iptables -A INPUT -s ! $LOCALNET -m limit --limit 1/s -j LOG --log-prefix '[IPTABLES NOMATCHINPUT] '以下のサイトを参考にさせてもらいながら設定を作った。
基本的には参考文献の上2つで大体完結するぐらいの内容。下手に変えない方がよかったかも知れない。
ファイアウォール構築(iptables) - Fedoraで自宅サーバー構築
連載記事 「習うより慣れろ! iptablesテンプレート集」
Man page of IPTABLES
D: Software/iptables - Debian GNU/Linux スレッドテンプレ
セキュリティ強化対策(Iptables編)
ルータ・ファイアウォールiptables)/Fedora Core6
・基本的には全部塞いで必要なところだけ開く(内側から外部へのアクセスも全面的には許可しない)
・ループバックインターフェイスで完結する通信だけは全面的に許可する
・各種攻撃からは防御を試みる
・外部の DNS サーバへの問い合わせを許可する
・HTTP、HTTPS、git、あと GMail で何かすることがあれば使う可能性がある 995,993,587,465 は外部への接続を許可する
・sources.list にリポジトリを追加する際に hkp 鍵サーバと通信する必要があるので 11371 番も外部への接続を許可
・外部からHTTPサーバへの接続を許可する
・外部からSSHサーバへの接続を許可する。ただしブルートフォース攻撃は怖いので過剰なアクセスはDROPするように
この他例えば SSH への接続が日本以外だったら蹴るような対策もすべきだが、現状は仮想PCで外部からは一切アクセスできない状態でテストが面倒なのでとりあえず保留にしてある。
あと外部の HTTP サーバなどに接続する際、ポート番号に 8080 などが使われていると接続できないという問題もある。この手の問題はできれば遭遇するたびに甘くしていく方針にしたい。
今回は仮想サーバで直接マシンのコンソールが開けるので簡単にテストが出来て、SSH が塞がれたままになっても問題なく作業が続行できたものの、リモートのサーバとなるとそうも行かない。
その辺に関してはここにいい説明があって、Windows でモニタを設定を変更するときのように「数秒後に元の状態に戻す」というところまでまとめてコマンドを投げておくことでリモートでのテストをしやすくする解説がある。
実際にリモートでしかできないような環境で設定することになったらこれも試してみようと思う。
参考文献のひとつめの URL では例えば LOCALNET を netstat から自動取得したりするようなコードがあるのだが、Firewall を設定するタイミングではまだその辺は上手く取得できないので IP に関しては直書きしておくことにした。
また国別IPリストの取得処理なども含まれているが、この辺はよく見てないものの設定切り替え時に一瞬無防備になっているような気がして怖いのでとりあえず何もしてない(恐らくiptables-save が吐き出すテキストの中の最後に commit があるので、iptables-restore を使って新しい設定に移行できればいいんじゃないか、という気はちょっとする)。
/etc/firewall.sh を実行して、例えば Windows 側で DOS 窓を2つ開いてサーバに対して同時に ping を打ったりして Ping of Death 対策の確認、Putty を何度も開いてブルートフォース攻撃対策の確認をしたりして、行った設定が上手くいっていることが確認できたら実際にこれがマシン起動時に有効になるようにする。
ln -s /etc/firewall.sh /etc/network/if-pre-up.d/iptablesこれで再起動して、Ping of Death の処理がうまく動いていることや SSH への過剰接続がブロックされることを確認したら iptables の設定は完了。
不安が残るもののとりあえずは大丈夫ということにしておこう。