懸案だったFreeBSD-5.xで mpd+pf によるファイアウォールの構築作業をした。OSは FreeBSD 5.2-RELEASE-p2。
/local/etc/pf.rulesはいろいろサンプルを見つつこんな感じにした。
このファイアウォールはIPv6の中継はしていないので、IPv6については特段の考慮をしていない。
ICMPについてはICMP対策にあるプロトコルのみ通すようにした。
scrub out all random-id max-mss 1414でMTUの調整をしている。
mpd.confにもset iface enable tcpmssfixと一応書いてあるんだけど、あんまり効き目がない模様。
# macros
int_if = "fxp0"
ext_if = "ng0"
lo_if = "lo0"
tcp_services = "{ ssh, smtp, http, domain, ntp }"
udp_services = "{ domain, ntp }"
netbios_ports = "{ 135, 137, 138, 139, 445, 1433 }"
icmp_in_types = "{echoreq, unreach, squench, timex}"
icmp_out_types = "{echorep, unreach, squench, timex}"
table <rfc1918_net> { 127.0.0.0/8, 192.168.0.0/16, 172.16.0.0/12, 10.0.0.0/8 }
table <in_net> { 192.168.0.0/16, 172.16.0.0/12, 10.0.0.0/8 }
# options
set block-policy return
set loginterface $ext_if
# scrub
scrub in all
scrub out all random-id max-mss 1414
# nat/rdr
nat on $ext_if from 192.168.0.0/16 to any -> $ext_if
rdr on $int_if proto tcp from any to any port 21 -> 127.0.0.1 port 8021
# filter rules
block log all
pass quick on $lo_if all
block drop in quick on $ext_if from <rfc1918_net> to any
# block drop out quick on $ext_if from any to $priv_nets
# IDENT (port 113)
block log quick inet proto tcp from any to any port = ident
# multicast address (for OSPF)
pass in quick from any to 224.0.0.0/8 allow-opts
pass out quick from any to 224.0.0.0/8 allow-opts
# ICMP
pass in quick inet proto icmp all icmp-type $icmp_in_types keep state
pass out quick inet proto icmp all icmp-type $icmp_out_types
# block NetBIOS
block in quick inet proto tcp from any to any port $netbios_ports
block in quick inet proto udp from any to any port $netbios_ports
block out quick inet proto tcp from any to any port $netbios_ports
block out quick inet proto udp from any to any port $netbios_ports
# outer to inner
pass in quick on $ext_if proto tcp from any to any port $tcp_services flags S/SA modulate state
pass in quick on $ext_if proto udp from any to any port $udp_services keep state
# pass in data mode connections for ftp-proxy running on this host. (see ftp-proxy(8) for details)
pass in quick on $ext_if proto tcp from any to $ext_if port 49152 >< 65535 flags S/SA keep state
# inner to outer
pass out quick on $ext_if proto {udp, tcp} from any to any keep state
# default rules
pass quick on $int_if all
block drop quick log on $ext_if all
/usr/local/etc/rc.d/pf.shはports/security/pf でやってきたサンプルのまま設置。
/etc/rc.confに以下の行を追加した。pf_logd については、同等の機能をdaemontools下に置いているので使っていない。
pf_enable="YES" pf_logd="NO" pf_conf="/local/etc/pf.rules"
ipfilterの時の流儀に沿って mpdの linkup スクリプトに以下のようにルールを読み込ませるコマンドを記述した。 (pfは動的にインターフェースのIPアドレスを検出する機構が存在するのでipfilterと違って大丈夫のような気もするけど)
/usr/local/sbin/pfctl -d /usr/local/sbin/pfctl -F all -f /local/etc/pf.rules /usr/local/sbin/pfctl -e
ちなみに/usr/local/sbin/pfctl -eで フィルタリングを有効にする というのに気付かなくてかなり悩んだ。
カーネルモジュールを読み込んだだけではデフォルトで有効にはなってないらしい。