tweet:2014:0812_01
NetBSD and pf
あとで整理して書き直す。
# 溜まってきているのが辛い。
NetBSD pfでさんざんハマったので、メモ書き。
NATとPacket Filter
NetBSD 6系に載っているpfの挙動で少しハマったので、メモ。
- pfの処理順序
- Packet incoming
- rdr処理
- nat処理
- packet filter処理
- Packet outgoing
つまり、Packet filterは「NAT処理された後」に適用される。Packet filter rule書く時に大ハマりするポイントなので注意。 (なお、当然、Packet filterを書けるI/Fも注意が必要)
---------------| pf |---------------|server| ext_if int_if この構成の時に、以下の1 NATルール、4パケットフィルタールールを使って実験 rdr pass on $if_ext proto { tcp,udp } from any to $ext_if -> $server block drop quick on $if_ext proto {tcp,udp} from any to $ext_if # Rule 1 block drop quick on $if_int proto {tcp,udp} from any to $ext_if # Rule 2 block drop quick on $if_ext proto {tcp,udp} from any to $server # Rule 3 block drop quick on $if_int proto {tcp,udp} from any to $server # Rule 4
それぞれのFilterルールをコメントアウトしたりしながら調べると、Rule 4のみが反映される。
- パケットが入ってくる$ext_ifではFilteroutできない。
- NAT前のアドレスではFilteroutできない。
Hair-Pin NAT
----------| pf |----------+----------|server-A| ext_if int_if | +----------|server-B| rdr pass on $if_ext proto { tcp,udp } from any to $ext_if -> $server <code> この構成において、Server-Bからpfの$ext_ifのアドレス(いわゆるGlobal Address)に対してQueryを投げるとうまく動作しない。 これは、Server-Bからpfのext_ifにパケットを投げると、pfはint_ifから受け取ったパケットなので、NAT処理をしないから。 この状況は、いわゆるLoad Balancer構成を組んでいて、Multi tenantのサービスをしている時に困る場合がある。 このような時に、Server-B → int_if → Server-A に通信が出来れば良いと考えて、以下のruleを突っ込む <code> rdr pass on $if_int proto { tcp,udp } from $serverB to $ext_if -> $serverA
これで一見動きそうに見えるが、実はそうは問屋が卸さない。
何が起こるかを表にすると、こんな感じ。
node | Src Addr | Dest Addr | 備考 |
---|---|---|---|
ServerB | ServerB | if_ext | |
pf | ServerB | if_ext → ServerA に変換 | NAT処理 |
ServerA | ServerB | ServerA | |
ServerAで内部処理 | |||
ServerA | ServerA | ServerB | |
pf | ServerA/Bは同一セグメントなので、pfにパケットがこない | ||
ServerB | ServerA | ServerB |
これでは、TCPでもUDPでも「正しく」通信出来ているとは云えない。通常は、このようなパケットは破棄され、通信出来ない。
本来は、こうなって欲しい
node | Src Addr | Dest Addr | 備考 |
---|---|---|---|
ServerB | ServerB | if_ext | |
pf | ServerB → if_int | if_ext → ServerA に変換 | NAT処理 |
ServerA | if_int | ServerA | |
ServerAで内部処理 | |||
ServerA | ServerA | if_int | |
pf | ServerA → if_ext | if_int → ServerB | NAT処理 |
ServerB | if_ext | ServerB |
というわけで、突っ込むべきRuleはこうなる
rdr pass on $if_int proto { tcp,udp } from $serverB to $ext_if -> $serverA nat on $if_int proto { tcp,udp } from $serverB to $serverA -> $if_int
全ポートを処理すれば良いのなら、binatでいいのだが、port 53だけ、このような処理をしたい場合には、nat(Src-NAT)とrdr(Dest-NAT)を組み合わせて二重変換を行わなければならない。
ちょいと特殊な設定なので、まぁ、普通は必要ないよね。
tweet/2014/0812_01.txt · 最終更新: 2014/08/12 01:00 by 127.0.0.1