
我正在尋找與 linux 等效的 Macos 命令:
sudo iptables -t nat -A POSTROUTING -o en0 -j MASQUERADE
我想要這樣做的原因是我有一個具有預設路由的 VPN,但我希望某些應用程式透過物理上行鏈路而不是 VPN。
使用pfctl
我做了以下事情:
pass out route-to (en0 192.168.4.1) group skipvpn flags any
我的網關的 IP 位址在哪裡192.168.4.1
,這似乎確實將來自skipvpn
群組中應用程式的所有資料包路由到en0
介面(而不是隧道)。我使用以下方法驗證這一點tcpdump
然而,所有已重新路由的資料包的「來源 ip」仍然具有 VPN 的來源 ip(範圍10.0.0.0/8
ip),這當然會導致事情中斷(即返回的資料包永遠無法找到返回的路..)
結果我嘗試nat
使用以下命令來獲取來源 ip:
nat on en0 from any to any -> en0
但這確實不是看起來工作正常,來源 IP 仍然損壞,並且與我的介面的來源 IP 不對應en0
。
如何確保這些重新路由的封包的來源 ip 設定正確?
答案1
— Mac OS 的 Pf 不會為你做這件事。原因如下:
如果你看一下它的手冊你會發現NAT 正在發生前濾。但 NAT 規則並不像過濾規則那樣支援所有類型的標誌。也就是說,在執行 NAT 時無法檢查套接字的所有權。您可以限制 NAT 規則的適用性,例如來源 IP 或目標 IP,但不能限制所有權。
另外值得一提的是在 NAT 處理期間 Pf 進行正常的路由查找。這意味著您根本無法工作 - 資料包將根據當時核心的路由表進行路由。在您的情況下,它們被調度透過預設路由的介面(即 VPN 介面)發送。他們將使用 VPN 介面的位址作為他們的來源 IP — 這對於正常的路由查找來說並不奇怪,但顯然不符合您的計劃。nat on en0
簡單總結一下矛盾:
- 如果您不進行 NAT,則在
route-to
應用時您的來源 IP 是錯誤的 - 您的 NAT 規則應在預設路由介面 (VPN) 上設置,同時將來源 IP 變更為 IP非VPN介面,如:
nat on vpn0 … -> (en0)
- 但OTOH,你不能擁有自訂 NAT(透過所有權),並且如果你無論如何都進行 NAT,那麼應該透過 VPN 傳輸的流量將具有錯誤的來源 IP。
PS Mac OS 的 Pf 中的實際狀態是更糟。 NAT 完成後,所有權匹配也不會在過濾規則中運作。