昔、NetBSDでマルチホームという記事を書いたが、問題を1つ見付けた。
set block-policy returnなど、block時にパケットを落とすだけじゃなくてダメよんと返事するような設定をしていた場合、その返事はdefault routeへ行ってしまうようだ。先の記事の最後の例で言えば、addr B宛てにたとえばtelnet接続が来ると、これはblock return in log allにマッチするので、pfはTCP resetを返そうとする。このパケットはどういう訳かdefault routeを通って、つまりpppoe0からISP A側へ行ってしまうのだ。
ソースコードを斜め読みしたところ、TCPの場合パケットとルールの比較をするキモの部分はpf.cのpf_test_tcp()で、block return/return-rstのときはpf_send_tcp()でTH_RST|TH_ACKを送っている。pf_send_tcp()では、このパケットはPFが作ったのよ、という印 (PACKET_TAG_PF_GENERATED) を付けてip_output()に渡す。ip_output()からはPFのフックpfil4_wrapper()を呼出すが、そこから呼ばれるpf_test()は真っ先にPACKET_TAG_PF_GENERATEDを調べてこの印がついていると何もしない。つまり、このTCP resetパケットはPFを通らないので、pppoe1のキューに移動されることもなく、そのままpppoe0経由で外へ出ていってしまう。
ということで、こういうことをやろうとしている人は、set block-policy dropとした方がよさそうだ。
コメントする