Monday 26 November 2018

routing - How to do IP masquerading on MacOS 10.14+?


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

Where does Skype save my contact's avatars in Linux?

I'm using Skype on Linux. Where can I find images cached by skype of my contact's avatars? Answer I wanted to get those Skype avat...