[華語, cmn-Hant-TW]
FreeBSD 的 pf 相當的好用,尤其是在有兩個 gateway 的時候,可以精確的控制進出的 gateway,大致上需要這樣子的設定 (在 /etc/pf.conf) 即可:
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 |
這樣可以把跑錯邊的封包丟回正確的路去,之前在 FreeBSD 6 上使用相當愉快。有遇到一個問題就是 icmp 封包走 $ext_gw1 回來 (系統的 default gateway 是 $ext_gw2) 只會收到第一個接著後面就失聯了,但是其他的 tcp udp 看起都正常運作,所以不是太大的問題,就沒理他了。
然後在把這台 server 昇級到 FreeBSD 7 之後,發現狀況反過來了。在設定檔完全一樣的情況下,icmp 通了,但是 tcp 斷掉了,這樣子問題就很大。交叉測試確定不是線路的問題之後,那就是設定的問題了。
測了一下發現想要從 $ext_gw1 進來建立的連線,回應的時候卻從 $ext_gw2 出去,試了好多方法都沒無解,再仔細看了一下 pf.conf 的 manual pages 裡面有沒有什麼 tcp only 的設定,然後就發現了 flag 這一個參數,照敘述來看就是說預設是 S/SA,然後如果你想要減少限制的話可以設成 any,但是搭配其他的可能會比較不穩定,啊我也懶得去仔細看這些參數是在幹嘛的,就拿 any 直接試了。沒想到居然可以用 (理論上應該有更合條件的設定,不過我不想去看文件了),而分開設好的話 icmp 也可以依然正常回應,沒有 FreeBSD 6 時代的問題,改過的設定檔:
pass out on $ext_if1 route-to ($ext_if2 $ext_gw2) proto { udp, icmp } from $ext_if2 to any pass out on $ext_if2 route-to ($ext_if1 $ext_gw1) proto { udp, icmp } from $ext_if1 to any pass out on $ext_if1 route-to ($ext_if2 $ext_gw2) proto tcp from $ext_if2 to any flags any pass out on $ext_if2 route-to ($ext_if1 $ext_gw1) proto tcp from $ext_if1 to any flags any |
把 tcp 和 icmp, udp 分別處理,運作的比之前還要順暢。後來想想在之前版本上面的設定有對的話,或許也可以正常處理 icmp 封包。不過手邊沒有適合的 FreeBSD 6 的機器可以拿來測試,所以也就不去測試這個了。