PF pf rule to NAT all interfaces except en0 and en1

Situation: VPN server, hosting OpenVPN and L2TP connections. OpenVPN connections share a "utun" interface, one per OpenVPN server process. L2TP connections each get a unique "ppp" interface. Given the variable number & names of virtual interfaces, the easiest way to capture all of the potential interface permutations for NAT is a pf rule like this:

nat on en0 from ! (en0) to any -> (en0:0)

That works great. Except now the server has a second physical interface, en1, and obviously pf will NAT traffic coming from that interface. What is the correct way to rephrase the above pf rule so that neither en0 nor en1 gets NATted, but everything else does? I'm not seeing any good examples of this. Can't use a table, might be able to use a macro, but not sure of the proper syntax for that.
 
and obviously pf will NAT traffic coming from that interface.
No, that's not obvious. Why would it source NAT incoming traffic on another interface? Your rule only says something about outgoing traffic on en0.

Suppose your en0 has IP address 10.0.0.1 (lets keep it simple), then your rule translates to:
Code:
nat on en0 from !10.0.0.1 to any -> 10.0.0.1
nat on only operates on the outgoing traffic of that interface. Then the source address of a packet is translated to 10.0.0.1, and a state is kept for the return traffic. So it knows 'this' packet has to return to the original IP.

Now. If you have an IP packet coming in on en1, nothing is going to happen to it. The system is going to look at the destination address of that packet to determine if it has to route it somewhere else. Only if it determines the best route is out of en0, then the packet will pass your rule and have its source address translated.

The from !(en0) is an address not an interface. So the rule only applies to traffic routed out of en0 and the source address of that packet can be anything except 10.0.0.1.
 
That's why you make the big bucks.

So the only time this NAT rule would affect traffic associated with en1 would be if the routing table determined that traffic coming into en1 needed to route out of en0. Which shouldn't happen in this setup. I think I was missing the fact that "!(en0)" was actually referencing the default address on that interface, not the interface itself. I was thinking purely in terms of all the various interfaces, physical and virtual.

Thank you for the brief tutorial. It makes perfect sense now that you've explained it.

I know Thanksgiving isn't really a thing there, but we do share a good bit of common history in that regard through the Puritans...so, Happy Thanksgiving anyway!
 
Back
Top