Getting IPsec to Work Through NAT on pfSense
Most people hit a wall when they try to set up an IPsec VPN where one or both endpoints sit behind NAT. The tunnel just refuses to come up. You check the logs, you see phase 1 and 2 proposals matching, pre-shared keys are correct, and still nothing. It's frustrating because the configuration looks right on paper. The issue is almost always related to how NAT interacts with ESP packets and how the routing on both sides handles the return traffic. IPsec uses the ESP protocol, which doesn't have port numbers. Standard NAT devices can't track ESP sessions the way they handle TCP or UDP. When pfSense detects that the remote peer is behind a NAT device, it automatically encapsulates ESP inside UDP port 4500. This is NAT-T. Without it enabled, the tunnel fails about 90 percent of the time in real-world deployments where the remote site uses consumer-grade routers or carrier-grade NAT from an ISP. I spent about three weeks troubleshooting a site-to-site IPsec link between two offices where one location was behind a commercial CGNAT box. The phase 1 negotiation kept failing with no clear error. Turning on NAT-T resolved it immediately, but the bigger problem was getting the routing right on the pfSense side. You need to make sure the internal route to the remote subnet actually points through the VPN tunnel interface and not out the WAN. Check your routes with route -n or look at System Routing Routes in the GUI. If you see the remote subnet floating in the default route table, that's your problem.
Core Concepts Before You Start Configuring
IPsec has two phases. Phase 1 establishes the encrypted tunnel itself. Phase 2 defines what traffic actually flows through that tunnel. Both phases have their own encryption and authentication settings, and they operate independently. This means you can use different algorithms for each phase. Most people don't bother understanding this distinction until something breaks, and by then debugging takes significantly longer than it should. PFS, or Perfect Forward Secrecy, is another concept that matters more than most guides acknowledge. It forces a new key exchange for each SA in phase 2. Without PFS enabled, compromised keys from early in the tunnel's lifetime could theoretically decrypt later traffic. I always enable it. The performance hit is negligible on modern hardware, and the security improvement is straightforward.
Unlocking Secure Connectivity A Comprehensive Guide To Ipsec VPN With Nat On Pfsense
This guide covers the actual configuration steps. You need pfSense 2.6 or later. Earlier versions have known issues with certain NAT-T implementations that cause intermittent tunnel drops. I learned this the hard way when a tunnel I'd been running for eight months started dropping every 48 hours with no pattern I could correlate to anything in the logs. Go to VPN IPsec Interfaces tab. Select the WAN interface as the tunnel interface. This is non-negotiable when dealing with NAT. The key fields here are: Remote Gateway: Enter the public IP address or DDNS hostname of the remote peer. Do not enter a private IP address here. If the remote peer also uses DDNS, make sure the hostname resolves correctly before proceeding.
Get the Full Details

Phase 1 Proposal: Use aes256-sha256-modp2048 or stronger. I've seen guides recommend aes128-sha1-modp1024 for compatibility, but that's using 20-year-old defaults. Modern devices support the stronger algorithms without any performance penalty on pfSense hardware from the last five years. NAT Traversal: Set this to On. This is the critical setting for any setup involving NAT. Leave it off only if you have two directly connected public interfaces with no NAT device between them, which is increasingly rare. Pre-Shared Key: Use a proper random key. Generate one with openssl rand -hex 32 on the pfSense shell. Do not use a passphrase, a password from a password manager's display field, or anything you've used for another service. Preshared keys are transmitted in phase 1 negotiations in the clear after being hashed, and weak keys make brute-force attacks trivially easy against this protocol.
Phase 2 Configuration
Once phase 1 completes and shows as Established, move to the Phase 2 tab. The local subnet is your internal network. The remote subnet is whatever network sits behind the other peer. These must not overlap. If you've ever assigned 192.168.1.0/24 on both ends, the tunnel will negotiate successfully and then silently drop all traffic. This is one of the most common errors I encounter, and it's painful to debug because the UI shows everything as green. Phase 2 Proposal: aes256gcm128-sha256-128-modp2048 is the current recommended setting. GCM mode is faster than CBC on most modern CPUs because it's hardware-accelerated. If you're running pfSense on older ARM hardware, test the performance difference. On my test rig with an Intel J4125, GCM gave me about 15 percent better throughput at wire speed compared to CBC. Enable PFS. Set the DH group to match phase 1 or use modp2048 minimum. Anything less and you're accepting a known weakness that NSA-level adversaries can exploit with sufficient resources.
PMTU Discovery: Enable this. It prevents fragmentation issues that cause intermittent connectivity problems, especially over cellular links or any path with a reduced MTU. Without it, large packets get dropped somewhere in the middle and the connection appears to work until someone tries to transfer anything substantial.

The Routing Issue Nobody Talks About
This is where most guides stop and yours starts failing. When a client behind NAT initiates a connection through the IPsec tunnel, the return traffic needs a valid route back. On the pfSense side, go to Firewall Rules and make sure you have an allow rule on the VPN interface for the remote subnet. Then check System Routing Gateways. The gateway for the remote network should point to the IPsec tunnel, not the WAN gateway. I ran into a specific issue where the route table had two entries for the same remote subnet — one through the tunnel and one through the default route. pfSense picked the wrong one because of routing table priority rules. I fixed it by adding a static route with a higher priority and lower distance value than the default route. The command on the shell was route add -net 10.0.0.0/24 -gateway 192.168.100.1 -distance 1 replacing the values with your actual tunnel peer IP and target subnet. Another thing to verify: if the remote peer is also running pfSense, make sure its phase 1 local subnet and phase 2 remote subnet are the mirror image of yours. If you're connecting to a Windows host behind NAT, the local subnet on the Windows side should be the actual internal network of that host, not a dummy range. I wasted an afternoon once configuring a Windows client with 10.0.0.0/24 as the local subnet when the actual LAN was 172.16.0.0/16. The tunnel came up but no traffic flowed in either direction.
Known Limitations and When This Fails Completely
IPsec with NAT-T works well in most cases but has real limitations. Carrier-grade NAT from major ISPs is the biggest problem. Some CGNAT implementations do not forward UDP 4500 at all, which makes NAT-T impossible. In those cases you're stuck. The workaround is to ask your ISP for a public IP or use a different VPN protocol like WireGuard which handles NAT traversal differently through keepalive packets on UDP. Another limitation: IPsec doesn't scale well for more than a handful of remote peers on a single gateway. Each tunnel consumes CPU and memory for SA maintenance and encryption operations. If you're managing 50 or more remote sites, look into software like FreeSWAN or commercial SD-WAN solutions. pfSense IPsec is fine for small to medium deployments. Mobility is another weak point. If a client moves between networks — say from WiFi to cellular — the IPsec tunnel breaks and requires renegotiation. This can take 30 to 90 seconds depending on your timeout settings. For use cases requiring seamless handoff, consider IPsec in conjunction with a mobility solution or just use WireGuard which handles roaming much more gracefully.
Verification and Troubleshooting
After configuration, check the status page. VPN IPsec Status should show both phase 1 and phase 2 as Established with active byte counters. If counters are zero after several minutes of expected traffic, something is misrouted. Check the logs at View Logs IPsec for phase 1 and phase 2 negotiation details. Use diag_dump_states.php from the shell or Diagnostics States to see actual traffic flowing through the tunnel. If states appear but traffic still doesn't reach the destination, the issue is almost certainly routing on the remote side, not the pfSense side. For persistent issues that resist standard troubleshooting, capture a packet on the WAN interface with tcpdump filtered for esp or udp port 4500. Look at the raw packets. Sometimes the problem is visible in the packet structure itself — incorrect SPI values, malformed headers, or missing NAT-T indicators that the automatic detection failed to add.

The configuration itself is straightforward. The complications come from the edge cases: overlapping subnets, CGNAT blocking UDP 4500, routing table priority conflicts, and mismatched PFS settings between peers. Getting past those requires checking each variable methodically rather than guessing at what might be wrong.