I am looking for the equivalent Macos command to the linux:
sudo iptables -t nat -A POSTROUTING -o en0 -j MASQUERADE
The reason i want to do this is I have a VPN that has the default route, but i would like certain apps to go over the physical uplink rather than the VPN.
Using pfctl
i have done the following:
pass out route-to (en0 192.168.4.1) group skipvpn flags any
Where 192.168.4.1
is the ip of my gateway, and this does appear to route all packets from apps in the skipvpn
group to the en0
interface (rather than the tunnel). I verify this using tcpdump
However the 'source ips' of all the packets that have been re-routed still have the source ip of the VPN (a 10.0.0.0/8
range-ip), causing things to break of course (i.e returning packets can never find their way back..)
As a result I tried to nat
the source ips using this:
nat on en0 from any to any -> en0
But this does NOT appear to work, the source IPs are still broken, and do not correspond to the source ip of my en0
interface.
How do i ensure that the source ips are set correctly for these re-routed packets?
Answer
— Mac OS' Pf won't do this for you. Here's why:
If you'd take a look at its manual you'd find that NAT is happening before filtering. But NAT rules don't support all variety of hall-marks as filtering rules do. Namely there's no way to check for socket's ownership while doing NAT. You can restrict NAT rules' applicability with, say, source or destination IPs, but not ownership.
Another thing to mention is during NAT processing Pf's doing normal route look up. It means you won't have nat on en0
working at all — the packets are routed according to kernel's routing table at that moment. In your case they are dispatched to be sent via default route's interface which is VPN interface. And they would be using VPN interface's address as theirs source IPs — which is not surprising for normal route look ups, but obviously isn't playing along with your plan.
To summarise the contradictions, briefly:
- If you don't do NAT you have wrong Source IP when
route-to
is applied - Your NAT rule should be set on default route interface (VPN) while changing Source IP to IP of non-VPN interface, like:
nat on vpn0 … -> (en0)
- But OTOH you can't have custom NAT (by ownership) and if you do NAT anyways then traffic that is supposed to go via VPN would have wrong Source IP.
P. S. The actual state of things in Mac OS's Pf is even worse. After NAT is done ownership matching won't work in filtering rules either.
No comments:
Post a Comment