pfはOpenBSD由来の実装で、ipfilterがライセンス的な問題で継続利用が難しくなったため、新たに開発されたもの。FreeBSDでも今日、使えるようになっており、rc.confの設定だけで有効となる。
kernelの再構築
rc.confにおいて、pf_enableを設定すれば、kernel自体は再構築の必要はないようだ。あえて再構築したい場合は、以下を有効にする。なお、トラフィック制御等は、ALTQの付くoptionsを有効とする必要がある。
device pf
device pflog
device pfsync
options ALTQ
options ALTQ_CBQ
options ALTQ_RED
options ALTQ_RIO
options ALTQ_HFSC
rc.confの設定
pfを有効にするだけで良いが、必要に応じて、rulesの位置やpflogに関する設定などが行える。
pf_enable="YES"
pf_rules="/etc/pf.conf"
pflog_enable="YES"
pf.confの設定
OpenBSDのサイトでは、Load Balance Outgoing Trafficが紹介されている。exampleには具体的な設定が掲載されているけれど、若干設定を書き加えてみた。以下は、firewallが無効になっているとはいえ、ADSL回線で同時に2本を接続した上で、管内のサーバは片側の固定IPを使い公開する例。(確認環境では、ADSLを2本契約。InfoSphereの固定IP8個サービスと動的IPを持つOCNでインターネットに接続している。3枚のNICで、2枚をプロバイダ接続に、1枚を管内ネットワークに使っている。4枚のNICで、さらにDMZを設定しても良い。手元の環境では、PCIスロットが3本のため、DMZは設定していない。)
# ee /etc/pf.conf
lan_net="192.168.1.0/24"
server="{内部に用意した固定IPをスペース区切りで記入 1.2.3.4 1.2.3.5 1.2.3.6}"
direct="{経路指定したいIPをスペース区切りで記入}"
int_if="rl0"
ext_if1="tun0" #fxp0 ng0 ppp0 などと指定することもあろう。ifconfigでIPを取得しているものが良い。
ext_if2="tun1"
ext_gw1="固定IP"
ext_gw2="動的IP"
scrub in all
# nat outgoing connections on each internet interface
#no nat from any to $server # 管内のサーバはno natで指定しなくても良い。
#no nat from $server to any
nat on $ext_if1 from $lan_net to any -> ($ext_if1)
nat on $ext_if2 from $lan_net to any -> ($ext_if2)
# default deny
#block in from any to any
#block out from any to any
pass quick on lo0 all
# pass all outgoing packets on internal interface
pass out on $int_if from any to $lan_net
# pass in quick any packets destined for the gateway itself
pass in quick on $int_if from any to $server
pass in quick on $int_if from $lan_net to $int_if
# load balance outgoing tcp traffic from internal network.
pass in on $int_if route-to \
{ ($ext_if1 $ext_gw1), ($ext_if2 $ext_gw2) } round-robin \
proto tcp from $lan_net to any flags S/SA modulate state
# load balance outgoing udp and icmp traffic from internal network
pass in on $int_if route-to \
{ ($ext_if1 $ext_gw1), ($ext_if2 $ext_gw2) } round-robin \
proto { udp, icmp } from $lan_net to any keep state
# general "pass out" rules for external interfaces
pass out on $ext_if1 proto tcp from any to any flags S/SA modulate state
pass out on $ext_if1 proto { udp, icmp } from any to any keep state
pass out on $ext_if2 proto tcp from any to any flags S/SA modulate state
pass out on $ext_if2 proto { udp, icmp } from any to any keep state
# route packets from any IPs on $ext_if1 to $ext_gw1 and the same for $ext_if2 and $ext_gw2
pass out on $ext_if1 route-to ($ext_if2 $ext_gw2) from $ext_if2 to any
pass out on $ext_if2 route-to ($ext_if1 $ext_gw1) from $ext_if1 to any
# 固定IPの接続は必ず$ext_if1を経由させる
pass out on $ext_if2 route-to ($ext_if1 $ext_gw1) from $server to any
# 指定したIPへの接続は必ず$ext_if1を経由させる(うまく稼働せず)
pass out on $ext_if2 route-to ($ext_if1 $ext_gw1) from $direct to any
サービスの再起動
どちらを使っても良い。pfctlを使う方が一般的に紹介されている。rc.dのpfを再起動する方法は、確実な動作を期待した。
# pfctl -f /etc/pf.conf
# /etc/rc.d/pf restart
設定状況を確認する方法
# pfctl -s nat
# pfctl -s rules
参考
整理中
自マシンssh
$PIint tcp from $IFint:network to ($IFint) port ssh flags S/SA keep state
# pfctl -t badhost -Tadd 10.1.1.1 # テーブルへ追加
# pfctl -t badhost -Tdelete 10.1.1.1 # テーブルから削除
# pfctl -t badhost -Tshow # テーブルの一覧表示
http://www.daily-labo.com/content_22.html
table <test> const { 10.0.0.0/8 172.16.0.0/12 }
scrub in all
antispoof quick for $ext_if inet
block in on $ext_if from <test> to any
block out on $ext_if from any to <test>



