我正在寻找与 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 时无法检查套接字的所有权。您可以使用源或目标 IP 来限制 NAT 规则的适用性,但不能限制所有权。
另一件值得一提的是在 NAT 处理期间,Pf 进行正常路由查找。这意味着您根本无法工作——数据包根据当时内核的路由表进行路由。在您的情况下,它们被调度通过默认路由的接口(即 VPN 接口)发送。并且它们将使用 VPN 接口的地址作为其源 IP——这对于正常的路由查找来说并不奇怪,但显然不符合您的计划。nat on en0
简单总结一下这些矛盾:
- 如果你不做 NAT,那么
route-to
应用时源 IP 是错误的 - 您的 NAT 规则应在默认路由接口 (VPN) 上设置,同时将源 IP 更改为非VPN界面,如:
nat on vpn0 … -> (en0)
- 但另一方面,您不能拥有自定义 NAT(按所有权),并且如果您无论如何都执行 NAT,那么应该通过 VPN 传输的流量将具有错误的源 IP。
PS Mac OS 的 Pf 的实际状态是更糟。NAT 完成后,所有权匹配在过滤规则中也将不起作用。