iptablesの設定の見直し

■Debian Lennyにファイアウォールを設定する。

 ・許可制限対象はINPUT/FORWARDのIPv4の稼動中のポートのみ。
 ・本来はローカルネットワークやOUTPUTの設定も必要だが、
  上位サーバの仕事なので今回は行わない。
 ・いずれのルールにもマッチしない場合は、ログを出力して破棄する。

$ echo "iptables iptables-save" | xargs whereis
iptables: /sbin/iptables /usr/share/iptables /usr/share/man/man8/iptables.8.gz
iptables-save: /sbin/iptables-save /usr/share/man/man8/iptables-save.8.gz

$ dpkg -L iptables | grep /sbin/
/usr/sbin/iptables-apply
/sbin/ip6tables
/sbin/ip6tables-restore
/sbin/ip6tables-save
/sbin/iptables
/sbin/iptables-restore
/sbin/iptables-save

■準備

 tcpのすべてのソケットを数字で表示。
 かつ、ipv4のポートを数の小さい順に並べる。
 ※uniqはIPやホストによる重複を排除する。

$ netstat -tan --protocol inet | awk -F\: '{print $2}' | awk '{print $1}' | sort -n | uniq

■/etc/servicesで引けるものを一覧する

$ netstat -tan --protocol inet | awk -F\: '{print $2}' | awk '{print $1}' | sort -n | uniq | \
for list in `xargs`;do sed s/"\t"/":"/g /etc/services | grep --color "\:$list\/tcp"; done
ftp::21/tcp
smtp::25/tcp::mail
pop3::110/tcp::pop-3::# POP version 3
sunrpc::111/tcp::portmapper:# RPC 4.0 portmapper
imap2::143/tcp::imap::# Interim Mail Access P 2 and 4
submission:587/tcp::::# Submission [RFC4409]
imaps::993/tcp::::# IMAP over SSL
pop3s::995/tcp::::# POP-3 over SSL

■マスカレードは行わない。

 $ netstat -M
netstat: no support for `ip_masquerade' on this system.
■外からのssh接続を受け付ける。

 例)外からはポート8022でNAT変換、Debian側ではポート22で応答
   INPUTとFORWARDの両方を設定。

iptables -A INPUT -p tcp --dport 22 -j ACCEPT
iptables -A FORWARD -i eth0 -p tcp --dport 22 -j ACCEPT

$ sudo nmap -sX localhost -p 8022 | grep 8022
8022/tcp open|filtered unknown

■外からのwwwに対応する設定(普通はこんな風にはやらないw)
 iptablesは8080ポートの受信を許可、外からの80ポートの転送を許可する

iptables -A INPUT -p tcp --dport 8080 -j ACCEPT
iptables -A FORWARD -i eth0 -p tcp --dport 80 -j ACCEPT

★以下のようにすることで、sshでアクセスし、かつトンネルセッションを繋げた時のみ
 webサーバにアクセス出来る。つまり、自分が見える設定を行った時のみ外から見れるwebサーバです。
 転送先ポートはapacheでもリバースプロキシでも構いません。
 sshのトンネルセッションをログアウトすると使えなくなります。
 スクリプトでなく、特定のputtyの設定からだけ等にすると、
 更に自分でさえどうやって繋げるのか分からなくなります。
 ※webクライアントがproxy経由の場合、直ぐに見れなくなるわけではないので注意します。

例)
[クライアントPC]->[ブラウザ]->[プロキシ]->[ルータのNAT]->[ルータのNAT]->[外部]
[外部]->[ルータのNAT]->[ルータのNAT]->[Debianのsshトンネル]->[リバースプロキシ]->[apache]

# vim www.sh
#!/bin/bash
ssh -p 22 -g -L 80:localhost:8080 usr@localhost
# chmod 500 www.sh
# ./www.sh
# ps -ef | grep :8080 | grep -v grep | awk '{print $2}'
5123
# exit
logout
Connection to 127.0.0.1 closed.

★www.sh実行前、sshトンネルセッションログアウト後

$ sudo nmap -sX localhost -p 80 | grep 80
80/tcp closed http

★www.sh実行中

$ sudo nmap -sX localhost -p 80 | grep 80
80/tcp open|filtered http

■後は普通に(?)

 参考URL:http://d.hatena.ne.jp/doublefree/20101124/1290573124

一時的に使用するポートはその都度、自身でiptablesコマンドを使用し許可する。

--------------------------------------------------------------------------------
■2011/11/05追記
 itables-saveについての追記とシステムメールの追加。

参考URL
http://www.asahi-net.or.jp/~aa4t-nngk/ipttut/output/index.html

■iptablesコマンドは「-c」オプションで保存が出来る。
 上記参考URLの「8.3. iptables-save」から。

# touch /etc/iptables-save
# chmod 600 /etc/iptables-save

# save configuration
iptables-save -c > /etc/iptables-save

■上記参考URLの「8.4. iptables-restore」からのリストア方法。

# cat /etc/iptables-save | iptables-restore -c

■カウンタの状況はメールで送信する。

# vim iptables-report.sh
THISDATE=`env LANG=C date '+%Y/%m/%d %H:%M:%S'`
cat /etc/iptables-save | mail -s "iptables report ${THISDATE}" root

# chmod 500 iptables-report.sh
# ./iptables-report.sh

私の環境ではベースとなる「firewall.sh」の後に、
サービス毎に必要となるポートを開放するスクリプトを追加する形式を取る。

その為、以下の制限が生まれる。

 ・一時的な追加分まで戻ってしまうiptables-restoreでは戻せない。
  (テーブルやカウンタのリセットが必要)

 ※システムメールの送信箇所は、別のログに出力しても構わない。
--------------------------------------------------------------------------------

$ sudo cat firewall.sh
#!/bin/sh
PATH=/sbin:/usr/sbin:/bin:/usr/bin

# system mail
THISDATE=`env LANG=C date '+%Y/%m/%d %H:%M:%S'`
cat /etc/iptables-save | mail -s "iptables report ${THISDATE}" root

# clear setting
iptables -F

# clear packet counter
iptables -Z

# policy
iptables -P INPUT DROP
iptables -P FORWARD DROP
iptables -P OUTPUT ACCEPT

# allow lo
iptables -A INPUT -i lo -j ACCEPT

# allow established
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT

# allow icmp
iptables -A INPUT -p icmp -j ACCEPT

# allow port

# custom www
iptables -A INPUT -p tcp --dport 8080 -j ACCEPT
iptables -A FORWARD -i eth0 -p tcp --dport 80 -j ACCEPT

# ssh
iptables -A INPUT -p tcp --dport 22 -j ACCEPT
iptables -A FORWARD -i eth0 -p tcp --dport 22 -j ACCEPT

# squid
iptables -A INPUT -p tcp --dport 3128 -j ACCEPT

# disallow else
iptables -A INPUT -j LOG --log-prefix "IPTABLES_INPUT_LOG : " --log-level=info
iptables -P INPUT DROP

# save configuration
iptables-save -c > /etc/iptables-save

# system mail
THISDATE=`env LANG=C date '+%Y/%m/%d %H:%M:%S'`
cat /etc/iptables-save | mail -s "iptables report ${THISDATE}" root


■ログの確認
 ※UDPの設定をしていないので、ログが沢山出るはずです。。。

sudo tail -f /var/log/kern.log | grep IPTABLES_INPUT_LOG --color

■設定の確認

$ sudo /sbin/iptables -L | grep 22
ACCEPT tcp -- anywhere anywhere tcp dpt:22

$ sudo /sbin/iptables -L -v | grep REJECT
23 1360 REJECT tcp -- any any anywhere anywhere tcp dpt:smtp reject-with icmp-port-unreachable
1 40 REJECT tcp -- any any anywhere anywhere tcp dpt:submission reject-with icmp-port-unreachable

$ sudo /sbin/iptables -L -v | grep DROP
Chain INPUT (policy DROP 53 packets, 6364 bytes)
Chain FORWARD (policy DROP 0 packets, 0 bytes)

■表示されないポートを番号で見たい。

$ sudo /sbin/iptables -L -v -n | grep 8080
0 0 ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:8080