Manually recreating IPsec NAT/BINAT rule with Outbound NAT table



  • tl;dr Is it possible to manually craft the same IPsec, NAT and Rules config as would be created with the IPsec P2 NAT/BINAT filled in, without actually filling that field in...?

    I am trying to convert some complex IPsec logic from an existing Cisco ASA to pfSense, and am hitting a problem with regards to NAT/BINAT. In the past, I have successfully performed this migration to Fortigate and Sonicwall, but would prefer to use pfSense as it is often more cost-efficient within a cloud platform.

    The tunnel in question has a defined encryption domain (local/remote network subnet) where the local subnet is not the actual LAN subnet, but a hide-NAT subnet pre-agreed with the tunnel partner.

    The intention is to establish the tunnel between the hide-NAT subnet and the target subnet; then outbound-NAT the real source addresses of my end-users (which appear in multiple subnets on the LAN side) to appear to be a single, speciifc address in the hide-NAT subnet. Later I intend to use the remaining addresses in the hide-NAT subnet as port-forward targets to serve inbound requests from the partner to specific dedicated servers on my side of the tunnel.

    (Please leave aside concerns for the moment as to why I am trying to do this -- it is simply a migration exercise from an existing device that can.)

    For example, the partner's subnet is 172.16.111.0/24 and the pre-agreed hide-NAT subnet is 192.168.222.0/28. My test client (10.1.1.1) is on a clearly different subnet, but it is one that routes to the LAN interface (and there are static-routes back to each "LAN" subnet via their various next-hops).


    For now, I have the following two rules (I intend to lock them down to specifics, later):

    • Action: Pass
    • Interface: LAN
    • Source: Any
    • Destination: 172.16.111.0/24

    ...and:

    • Action: Pass
    • Interface: IPSec
    • Source: Any
    • Destination: Any

    Attempt #1
    I configure the IPsec Phase 2 as:

    • Local: Network: 192.168.222.0/28
    • Remote: Network: 172.16.111.0/24
    • NAT/BINAT: None

    ...the IPsec tunnel establishes correctly with the partner device (both Phase 1 and Phase 2) and I see SAD and SPD entries.

    I set the Outbound NAT mode to Hybrid and add an entry to the table that is:

    • Source: any
    • Destination: 172.16.111.0/24
    • Protocol: any
    • Translated: 192.168.222.1/32

    I initiate traffic from the test client. I can see the USER_RULE match in the Firewall log, but it is not sent outbound down the established IPsec tunnel. My assumption is that NAT is not taking place, but I am happy to be challenged on this.

    Attempt #2
    I configure the IPsec Phase 2 as:

    • Local: Network: 0.0.0.0/0
    • Remote: Network: 172.16.111.0/24
    • NAT/BINAT: Network: 192.168.222.1/32

    ...the IPsec tunnel does not establish correctly with the partner device, because the Phase 2 setting is mismatched (192.168.222.1/32 instead of 192.168.222.0/28).

    Attempt #3
    I configure the IPsec Phase 2 as:

    • Local: Network: 0.0.0.0/0
    • Remote: Network: 172.16.111.0/24
    • NAT/BINAT: Network: 192.168.222.0/28

    ...the IPsec tunnel establishes correctly with the partner device (both Phase 1 and Phase 2) and I see SAD and SPD entries.

    I have no manually-added Outbound NAT rules.

    I initiate traffic from the test client. I can see the USER_RULE match in the Firewall log, but it is not sent outbound down the established IPsec tunnel. Again, my assumption is that NAT is not taking place.

    Attempt #4
    I configure the IPsec Phase 2 as:

    • Local: Network: 0.0.0.0/1 (this was an accident, but it is interesting)
    • Remote: Network: 172.16.111.0/24
    • NAT/BINAT: Network: 192.168.222.0/28

    ...the IPsec tunnel establishes correctly with the partner device (both Phase 1 and Phase 2) and I see SAD and SPD entries.

    I have no manually-added Outbound NAT rules.

    Strangely, this initially appears to work, but the partner's server sees the source has been translated 192.168.222.0 instead of 192.168.222.1, and are twitchy about it. I also know that this isn't technically any LAN source, but actually 0.0.0.0-127.255.255.255, and I know I have LAN sources in higher addresses (172/12 and 192.168/16, for example). Since I can't seem to choose the NAT address, my guess here is that some maths is happening that divides/distributes the billion-or-so addresses in 0.0.0.0/1 across the 16 addresses in 192.168.222.0/28, so I wouldn't be able to use the other addresses as inbound port-forward targets -- feel free to reeducate me here.


    If I run a command-line pfctl -sn after each attempt, the only difference I can see between the output is a single nat on enc0... statement:

    1. nat on enc0 inet from any to 172.16.111.0/24 -> 192.168.222.1 port 1024:65535
    2. no nat on enc0 is generated
    3. no nat on enc0 is generated
    4. nat on enc0 inet from 0.0.0.0/1 to 172.16.111.0/24 -> 192.168.222.1

    I assume that the underlying IPsec config (ipsec.conf?) is also configured differently when I use the NAT/BINAT field -- I'm guessing that setting the NAT/BINAT field changes what is configured as the left parameter? Does something else happen when I fill in the NAT/BINAT field for IPsec/P2, in addition to the creation of the nat statement?

    If not, then I don't immediately understand why the nat statement generated in the fourth attempt is functionally different from the one generated in the first attempt (i.e. why does the subnet being 0.0.0.0/1 work, but not when it is any). Can someone here enlighten me? Is it to do with the addition of the port... clause (added by the Outbound NAT rule) and, if so, can that be suppressed?

    Secondarily, I also don't understand why the NAT/BINAT in the second and third attempts don't generate a nat statement. Surely 0.0.0.0/0 should work (or be should be generated as any)? Is this is a pfSense bug?


Log in to reply