firewallの構築(ipfilter)

1.なぜipfilterか?

ipfwよりも細かく設定できる
ルールのテストが出来る
内部のユーザにはルータの様に見えるので、壁を(ほとんど)意識しないで済む
マシンのリソースをほとんど消費しない(カーネルのみ)
パケット処理が高速

2.設定

カーネルの再構築、rc.confの設定などはPPPoA,PPPoEの項目で既に設定してあるものとして話を進めます。

/etc/ipf.rules を編集する
##LAN側IP 192.168.1.0-255
##LAN側NIC fxp0
##WAN側NIC xl0
##PPPoEは「xl0」ではなく誰でも「tun0」になるのでご注意下さい
##WAN側IP xxx.yyy.zzz.aaa

block in log quick from any to any with ipopts frag
block in log quick proto tcp from any to any with short

############################################
# 外部(Internet)からの入力(グループ 100)

pass in on xl0 all head 100

# アドレス偽装防止
block in from 127.0.0.0/8 to any group 100
block in from xxx.yyy.zzz.aaa/32 to any group 100
block in from 192.168.1.0/24 to any group 100

# プライベートアドレスやマルチキャストなどの破棄
block in from 10.0.0.0/8 to any group 100
block in from 172.16.0.0/12 to any group 100
block in from 192.168.0.0/16 to any group 100
block in from 0.0.0.0/8 to any group 100
block in from 169.254.0.0/16 to any group 100
block in from 192.0.2.0/24 to any group 100
block in from 224.0.0.0/4 to any group 100
block in from 240.0.0.0/4 to any group 100

# NetBIOS (port 137-139)
block in quick from any port 136 >< 140 to any group 100
block in quick from any to any port 136 >< 140 group 100

# UDP パケットをデフォルトで拒否
block in proto udp all group 100

# 接続された TCP パケットを許可
pass in quick proto tcp all flags A/A group 100

# 外部からの SSHとtelnetを拒否
block in log quick proto tcp from any to any port = 22 group 100
block in log quick proto tcp from any to any port = 23 group 100

# 外部からのWEBMINを拒否
block in log quick proto tcp from any to any port = 10000 group 100

# 外部からのsquidを拒否
block in log quick proto tcp from any to any port = 8080 group 100

# 外部からのdelegateを拒否
block in log quick proto tcp from any to any port = 3128 group 100

# 外部からのSWATを拒否
block in log quick proto tcp from any to any port = 901 group 100

# 外部からの SMTP 接続開始を許可(smtpサーバーが有る場合)
pass in quick proto tcp from any to any port = 25 flags S/SA group 100
# IDENT には答えない
block return-rst in quick proto tcp from any to any port = 113 group 100

# 外部からPOPには応答しない
block in quick proto tcp from any to any port = 110 flags S/SA group 100

# DNS サーバを立てている場合
pass in quick proto tcp from any to any port = 53 flags S/SA group 100
pass in quick proto udp from any to any port = 53 group 100
pass in proto udp from any port = 53 to any group 100

# WWW サーバを立てている場合
pass in quick proto tcp from any to any port = 80 flags S/SA group 100
pass in quick proto tcp from any to any port = 443 flags S/SA group 100

# FTP サーバーを立てている場合
pass in quick proto tcp from any to any port = ftp flags S/SA keep state group 100
pass in quick proto tcp from any to any port = ftp-data flags S/SA keep state group 100
# FTP PASV用に一部開放する(ポート番号は参考で7030-7050の場合)
pass in quick proto tcp from any to any port 7029 >< 7051 flags S/SA keep state group 100

# それ以外の外部からの TCP 接続を拒否し、ログに残す
block in log quick proto tcp all flags S/SA group 100

# 外部の DNS に問い合わせた帰りのパケット
pass in proto udp from any port = 53 to any group 100

# NTP の帰り
pass in proto udp from any port = 123 to any group 100

# 内部から外部への ping のみ許可
block in proto icmp all group 100
pass in proto icmp all icmp-type 0 group 100

# RFC2979
pass in proto icmp all icmp-type 3 group 100

############################################
# 外部への出力(グループ 200)

pass out on xl0 all head 200

# アドレス偽造防止
block out from 127.0.0.0/8 to any group 200
block out from any to 127.0.0.0/8 group 200
block out from any to xxx.yyy.zzz.aaa/32 group 200

# プライベートアドレスやマルチキャストなどの破棄
block out from any to 10.0.0.0/8 group 200
block out from any to 172.16.0.0/12 group 200
block out from any to 192.168.0.0/16 group 200
block out from any to 0.0.0.0/8 group 200
block out from any to 169.254.0.0/16 group 200
block out from any to 192.0.2.0/24 group 200
block out from any to 224.0.0.0/4 group 200
block out from any to 240.0.0.0/4 group 200

# NetBIOS (port 137-139)
block out from any port 136 >< 140 to any group 200
block out from any to any port 136 >< 140 group 200

# 接続された TCP パケットを許可
pass out proto tcp all flags A/A group 200

# 外部の DNS サーバへの問い合わせを許可
pass out from any to any port = 53 group 200

# 外部への接続開始を許可
pass out proto tcp all flags S/SA group 200

# 外部の NTP サーバへの問い合わせを許可
pass out proto udp from any to any port = 123 group 200

# 内部から外部への ping のみ許可
block out proto icmp all group 200
pass out proto icmp all icmp-type 8 group 200

############################################
# 内部から来るパケット(グループ 300)

pass in on fxp0 all head 300
block in from 127.0.0.0/8 to any group 300
block in from 192.168.1.1/32 to any group 300
block in from xxx.yyyy.zzzz.aaaa/0xffffff00 to any group 300

############################################
# 内部へ出ていくパケット(グループ 400)

pass out on fxp0 all head 400
block out from 127.0.0.0/8 to any group 400
block out from any to 127.0.0.0/8 group 400
block out from any to 192.168.1.1/32 group 400

############################################
# ループバックへのルール(グループ 0)
# (最後にあっても OK)
pass in quick on lo0 all
pass out quick on lo0 all

/etc/ipnat.rules  (PPPoAの場合)
map xl0 192.168.1.0/24 -> 192.168.0.2/32 proxy port ftp ftp/tcp
map xl0 192.168.1.0/24 -> 192.168.0.2/32 portmap tcp/udp auto
map xl0 192.168.1.0/24 -> 192.168.0.2/32

/etc/ipnat.rules  (PPPoEの場合)
map tun0 192.168.1.0/24 -> 0/32 proxy port ftp ftp/tcp
map tun0 192.168.1.0/24 -> 0/32 portmap tcp/udp auto
map tun0 192.168.1.0/24 -> 0/32

3.ルールのテスト

ipftest コマンドでパケットがパスするかブロックされるかをテストすることができます
テストデータには tcpdump や etherfind のダンプも使用できます
手で記述する場合は、こんな風に書きます
# ipftest
# 1.2.3.4 は Internet 側のアドレス
in on xl0 tcp 123.123.123.123,2000 1.2.3.4,80
テストします
# ipftest -r ipf.simple -i ipf.test
in on xl0 tcp 123.123.123.123,2000 1.2.3.4,80
input: on xl0 ...
pass ip 40(20) ... <= ルール通過
ところがこのipftestが最近コンパイルエラーするようで、標準だとコンパイルされません。
手動でコンパイルしてもエラーするので困ったものです。
記入ミスがあるとデフォルトブロックなので宅内からもsshで接続できないので実機を触りに行かないといけないという…
何とか使えるようになってほしいものです。

一応テストしてから反映させるスクリプトを作成。
#!/bin/sh
/sbin/ipftest -r /etc/ipf.rules -i /root/ipftest.rules
if [ $? = 0 ]
then
/sbin/ipf -Fa -Z -f /etc/ipf.rules
else
echo "rule NG"
fi

4.再設定方法

これで立ち上げ直せば反映されますが、設定を変える度に電源入れ直しでは面倒なので
以下のようなコマンドで、立ち上げたまま修正したルールを反映することができます。
/etc/ipf.rulesを反映させる場合
  # ipf -Fa -Z -f /etc/ipf.rules
/etc/ipnat.rulesを反映させる場合
  # ipnat -CF -f /etc/ipnat.rules

また起動時はうまく設定が反映されないので、下記のようなファイルを追加します。
/usr/local/etc/rc.d/0000.ipfstart.sh
#!/bin/sh
ipf -Fa -Z -f /etc/ipf.rules

case $1 in
'start' )
if [ -r /etc/ipnat.rules ] ; then
/sbin/ipnat -f /etc/ipnat.rules
fi
;;
'stop' )
/sbin/ipnat -C
;;
* )
echo "usage : ipfstart.sh {start|stop}"
;;
esac
ファイル名の頭が0になっているのは、たぶんこれで一番最初に走るだろうと思ってこうしています。

以上でネットワークの設定は終了です。
さぁ〜ネットワークを接続して立ち上げ直して見て下さい!
うまくいかない場合があっても、めげずに説明をよく読んで見直して見てください。
1文字でも間違えていると馬鹿正直に動いてくれません。
これでブロードバンドルーターの出来上がりです、次からは各種サーバーソフトを動かしていきましょう!