pfでホスト名指定のテーブル作成

FreeBSDで標準的に使われるファイアウォールの一つであるpfでは基本的にはIPアドレス/ネットワークを指定してパケット通過の許可/不許可を行うが、ホスト名指定でのパケットの許可/不許可もできなくはない。

int_if = "em0"
ext_if = "ng0"
int_net = "{ 192.168.0.0/24 }"

table <private> const { 10/8, 172.16/12, 192.168/16, 169.254/16 }
table <example> persist file "/etc/pf_example"

set block-policy drop
set skip on { lo0, $int_if }
scrub in all

#NAT
nat on $ext_if from $int_net to any -> ($ext_if)

#不許可ルール
block in  quick on $ext_if from { <private>, <example> } to any
block out quick on $ext_if from any to { <private>, <example> }

#この後に許可系のルールを書く。

/etc/pf_example
abc.example.com
def.example.com
ghi.example.com
123.example.net
456.example.net
789.example.net

ホスト名を1行に1つずつ書く。

または、指定するホスト数が少ないのであれば5行目のような書き方(const)で指定するのもあり。

pfの再起動
# /etc/rc.d/pf restart

実際にはテーブル読み込み時に自動的にホスト名からIPアドレスを引いてテーブルに登録している。
ホスト名に対するIPアドレスの割当が変わらないのであればこれで終わりだが、IPアドレスが可変であるならテーブルを更新する必要がある筈。下のコマンドをcronに仕掛けて定期的に実行する。

# pfctl -Tr -t example -f /etc/pf_example

-Tr: テーブルのリプレース
-t: テーブル名の指定
-f: ファイル名の指定

登録するホスト名が多量だとテーブル読み込み(更新)時の名前解決に時間がかかるので注意。
また、ホスト名に対するIPアドレス割当てが目まぐるしく変化するなら対応しきれないので別の方法で。

ログの録り方・読み方

pfでパケットを記録したいことがある。
ログを録るのは基本的には以下2点+設定再読み込み。

/etc/rc.confに以下2行追記。
pflog_enable="YES"
pflog_logfile="/var/log/pf.log"

/etc/pf.confでログ指定のルールを書く。
block in  quick log on $ext_if from { <private>, <example> } to any
block out quick log on $ext_if from any to { <private>, <example> }

上の方の不許可ルール2つをログ録り付きにした。 ルールの途中に log を足すだけ。

# /etc/rc.d/pf reload

pfの設定再読込。

これでログを録ることができるが、ログの形式が通常のログのようにテキストファイルではないので、cat などで表示しようとすると盛大に化けるというかターミナルアプリによっては表示をリセットしなければならない目に合う。
FreeBSDでは標準でtcpdumpが入っているのでそれで読む。

% tcpdump -n -e -ttt -r /var/log/pf.log