Ubuntuデスクトップのファイアウォールを設定してみた
注意:以下の内容はUbuntu Desktop版での話です。Server版はまた別です。
ポートは塞がれているというよりは開けてないだけ
「Ubuntuでは標準で全てのポートが閉じているのでファイアウォールの設定は不要」などという文章をよく見かけるのだが、これはものすごい誤解を招いていると思う。
実際はポートを開けてLISTENするプログラムが標準では入っていない(設定されていない)というだけで、明示的に全てのポートがブロックされるように設定されているわけではない。
少なくとも今年の7月にUbuntu(8.04)を使い始めた時にはiptablesの定義も空っぽだったし、他のそれらしい設定も何もなかった。
この状態でApacheとか入れると当然のように80番ポートでLISTENし始めて、外部からもアクセスできるようになる。Apacheなど入れなくてもNautilusなどでファイルの共有設定をすれば、当然それに必要なポートが開く。そりゃそうだ。他にもバックグラウンド的な何かが動いてそうな気もする。
自分はこれを誤解していて、外部からの新規接続は全てブロックするように設定されていて、Apacheとかを立ち上げてもローカル内でしかアクセスできないよう良きに計らってくれているものだと思っていた。
iptablesによるフィルタリング設定
普通はデスクトップPCにサーバアプリなんて入れないからそれでも問題ないのかもしれないけど、WebエンジニアとしてはついついローカルにApacheとか入れちゃったりするので何かしら対策はしておきたいところ。*1
というわけでiptablesでファイアウォールの設定をしてみた。
Ubuntuではufwとかいうのを使うらしいんだけど、なにそれ食べられるの?状態だったので、いつも通りにiptablesコマンドを直に叩く。
1.自動起動するための下準備
Ubuntuのiptablesはシステムの起動時に自動的に設定を復元してくれるようにはなってないので、まずはそれを行う。
具体的には/etc/init.d/iptablesを用意してsysv-rc-confでランレベル毎に自動起動するように設定するだけなんだけど、元になるスクリプトがどこにもないので、ぐぐって見つけたUbuntuのフォーラムから拾ってくる。
http://ubuntuforums.org/archive/index.php/t-19106.html
導入方法も書いてあるのでその通りにするだけ。
ちなみにCentOS4からコピってきたものは動かなかった。
ともあれこれで/etc/init.d/iptables start|stop|saveができるようになったので、適当に設定してsaveして、システム起動時にstartするようにしておけば準備は完了。
2.設定を書いたスクリプトを用意
手で打ち込んでいくのはだるい、というか間違えると切ないのでシェルスクリプトにまとめる。
サーバ用のものを元にしてデスクトップで不要なもの必要なものを調整したものが以下のスクリプト。
ルータの内側にいるクライアントなのでSSHサーバの設定や東アジアフィルタなどは削った。OUTPUTの制限も省略。
Apacheはローカルだけでもよかったんだけど、同僚に見てもらったりするときのために開いている。
内側にいるという意味ではDoS系の防御設定もあまり意味がないのかもしれないが、やれることはやっておくに超したことはないので。
IP MessengerはメッセージだけならUDPでいいんだけど、ファイル転送をするにはTCPも開けなければいけない。
最初これに気づかずにはまった。
#!/bin/bash LOCALNET='xxx.xxx.xxx.xxx/12' INTERNAL_IP=`ifconfig eth0 | grep 'inet addr' | awk '{print $2}' | awk -F : '{print $2}'` # ゲートウェイ EXTERNAL_IP='xxx.xxx.xxx.xxx' # NATの設定を削除 #iptables -F -t nat #iptables -F -t mangle # 全てのルールを削除 iptables -F # 全てのユーザ定義チェインを削除 iptables -X iptables -Z # 基本的には外部からのパケットの通過を拒否 iptables -P INPUT DROP # 基本的には外部へのパケットの通過を許可 iptables -P OUTPUT ACCEPT # 基本的には他のインターフェイスへ再送信を拒否 iptables -P FORWARD DROP # lo( ループバック)からのINPUTを許可 iptables -A INPUT -i lo -j ACCEPT # lo( ループバック)からのOUTPUTを許可 iptables -A OUTPUT -o lo -j ACCEPT # 確立しているコネクションのINPUTを許可 iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT # 確立しているコネクションのOUTPUTを許可 iptables -A OUTPUT -m state --state ESTABLISHED,RELATED -j ACCEPT # DNS iptables -A OUTPUT -m state --state NEW -m tcp -p tcp --sport 53 -j ACCEPT iptables -A OUTPUT -p udp -m udp --sport 53 -j ACCEPT iptables -A INPUT -m state --state NEW -m tcp -p tcp --dport 953 -j ACCEPT # LSLDNS iptables -A INPUT -p udp --dport 5353 -d 224.0.0.251 -j ACCEPT # DHCP iptables -A INPUT -i eth0 -d 255.255.255.255 -p udp --dport 67 --sport 68 -j ACCEPT # IPスプーフィング対策 iptables -N ip_spoofing iptables -A ip_spoofing -m limit --limit 1/s --limit-burst 5 -j LOG --log-prefix '[iptables ip_spoofing] ' iptables -A ip_spoofing -j DROP iptables -A INPUT -i eth0 -s 0.0.0.0/8 -j ip_spoofing iptables -A INPUT -i eth0 -s 10.0.0.0/8 -j ip_spoofing iptables -A INPUT -i eth0 -s 127.0.0.0/8 -j ip_spoofing iptables -A INPUT -i eth0 -s 169.254.0.0/16 -j ip_spoofing #iptables -A INPUT -i eth0 -s 172.16.0.0/12 -j ip_spoofing iptables -A INPUT -i eth0 -s 192.0.2.0/24 -j ip_spoofing #iptables -A INPUT -i eth0 -s 192.168.0.0/16 -j ip_spoofing iptables -A INPUT -i eth0 -s 224.0.0.0/4 -j ip_spoofing iptables -A INPUT -i eth0 -s 240.0.0.0/5 -j ip_spoofing iptables -A INPUT -i eth0 -s 248.0.0.0/5 -j ip_spoofing iptables -A INPUT -i eth0 -s 255.255.255.255/32 -j ip_spoofing # 自分のグローバルアドレスによるeth0からのアクセスを拒否 #iptables -A INPUT -i eth0 -s $EXTERNAL_IP -j DROP # Ping of Death対策 iptables -N ping-of-death iptables -A ping-of-death -m limit --limit 3/s --limit-burst 12 -j ACCEPT iptables -A ping-of-death -m limit --limit 1/m --limit-burst 5 -j LOG --log-level info --log-prefix '[iptables ping-of-death] ' iptables -A ping-of-death -j DROP iptables -A INPUT -i eth0 -p icmp --icmp-type echo-request -j ping-of-death iptables -A FORWARD -i eth0 -p icmp --icmp-type echo-request -j ping-of-death # SYNフラッド攻撃対策 iptables -N syn-flood iptables -A syn-flood -m limit --limit 3/s --limit-burst 12 -j RETURN iptables -A syn-flood -m limit --limit 1/m --limit-burst 5 -j LOG --log-level info --log-prefix '[iptables syn-flood] ' iptables -A syn-flood -j DROP iptables -A INPUT -i eth0 -p tcp --syn -j syn-flood iptables -A FORWARD -i eth0 -p tcp --syn -j syn-flood # ポートスキャン対策 iptables -N port-scan iptables -A port-scan -m limit --limit 3/s --limit-burst 12 -j RETURN iptables -A port-scan -m limit --limit 1/m --limit-burst 5 -j LOG --log-level info --log-prefix '[iptables port-scan] ' iptables -A port-scan -j DROP iptables -A INPUT -i eth0 -p tcp --tcp-flags SYN,ACK,FIN,RST RST -j port-scan iptables -A FORWARD -i eth0 -p tcp --tcp-flags SYN,ACK,FIN,RST RST -j port-scan # NTP iptables -A INPUT -p udp --dport 123 -j ACCEPT # IPsec #iptables -A INPUT -p 50 -j ACCEPT #iptables -A INPUT -p 51 -j ACCEPT # Samba iptables -A INPUT -s $LOCALNET -p udp --dport 137 -j ACCEPT iptables -A INPUT -s $LOCALNET -p udp --dport 138 -j ACCEPT iptables -A INPUT -s $LOCALNET -p tcp --dport 139 -j ACCEPT iptables -A INPUT -s $LOCALNET -p tcp --dport 445 -j ACCEPT # HTTP/HTTPS iptables -A INPUT -s $LOCALNET -m state --state NEW -m tcp -p tcp --dport 80 -j ACCEPT iptables -A INPUT -s $LOCALNET -m state --state NEW -m tcp -p tcp --dport 443 -j ACCEPT # PostgreSQL #iptables -A INPUT -s $LOCALNET -m state --state NEW -m tcp -p tcp --dport 5432 -j ACCEPT # CUPS #iptables -A INPUT -s $LOCALNET -p udp -m udp --dport 631 -j ACCEPT # IP Messenger iptables -A INPUT -s $LOCALNET -p tcp -m tcp --dport 2425 -j ACCEPT iptables -A INPUT -s $LOCALNET -p udp -m udp --dport 2425 -j ACCEPT # ICMP #iptables -A INPUT -p icmp --icmp-type any -j ACCEPT iptables -A INPUT -j REJECT --reject-with icmp-host-prohibited
INTERNAL_IPのところは自分のIPアドレスを設定するんだけど、DHCPなのでどうしたらいいのかわからなかったので無理矢理引っこ抜いた。もう少しいいやり方はないんだろうか。
というわけで、一通り設定してみたけどなんか無駄なことしてる気がしてきた。つーか、むしろクライアントの場合はOUTPUTを制限するべき?
正直理解できてない部分もあるので、おかしい点があればコメント欄へおながいします。