IPsec/IKEv2: The NAT-Traversal Pitfall That Breaks Site-to-Site

Was this helpful?

Nothing feels more cursed than a site-to-site VPN that’s “established” while your apps scream timeouts. The dashboards are green. The tunnel is up. And yet: no packets make it through, or they make it through until Monday at 9:07 AM and then die like a houseplant in a server room.

This is where NAT traversal (NAT-T) earns its reputation. IKEv2 is solid engineering, but NAT devices are creative saboteurs: they rewrite addresses, expire mappings, mangle fragments, and occasionally “help” in ways that only make sense to the person who bought the firewall in 2014.

NAT-T in one sentence (and why it hurts)

NAT traversal lets IPsec keep working when either peer is behind NAT by encapsulating ESP inside UDP/4500, but the smallest mismatch in detection, ports, timers, or filtering turns “secure transport” into “secure silence.”

Here’s the core pain: plain IPsec ESP (protocol 50) isn’t NAT-friendly because NAT needs transport-layer ports to track flows. ESP has none. NAT-T solves this by wrapping ESP in UDP, giving NAT something to key on (src/dst IP + src/dst port). The wrap is simple. The ecosystem around it is not.

When NAT-T breaks, it tends to break in ways that waste your time:

  • The IKE SA comes up (UDP/500 works), but CHILD SAs carry zero bytes.
  • It works for a while, then dies after idle periods (NAT mapping expiration).
  • It only fails for one direction (asymmetric filtering, routing, or policy mismatch).
  • It only fails when traffic is large (PMTUD/fragmentation/MTU issues).

One relevant rule of thumb: if you see “tunnel up, no traffic,” stop staring at crypto proposals and start verifying NAT-T and data-plane reachability.

Joke #1: NAT is like a cat: it ignores standards, does what it wants, and you still have to support it.

What actually happens on the wire: IKEv2 + NAT detection + UDP encapsulation

IKEv2 phases that matter for NAT-T

IKEv2 is cleaner than IKEv1, but the NAT pieces are still subtle. The high-level flow:

  1. IKE_SA_INIT: negotiates algorithms, does Diffie-Hellman, exchanges nonces, and performs NAT detection.
  2. IKE_AUTH: authenticates peers (PSK/certs), establishes the IKE SA, and sets up the first CHILD SA(s).
  3. CHILD SA rekeys: periodic rekeying of the data-plane SAs.

NAT detection is done via NAT-D payloads. Each side hashes what it thinks the 4-tuple should be (addresses and ports). If the hashes don’t match what the peer sees, the peers conclude there’s NAT on-path and switch to NAT-T behavior.

Ports: UDP/500, UDP/4500, and the part people forget

Baseline IKEv2 uses UDP/500. If NAT is detected, the tunnel typically moves to UDP/4500 for IKE and for encapsulated ESP. That means:

  • UDP/500 must work (at least for initial negotiation).
  • UDP/4500 must work for ongoing IKE messages and the data plane when NAT-T is in use.
  • Some devices start on UDP/500, detect NAT, then continue on UDP/4500. If your firewall allows 500 but not 4500, you get the “handshake looks fine, traffic is dead” classic.

ESP vs NAT-T encapsulation

Without NAT-T, the data plane is ESP (IP protocol 50). With NAT-T, the data plane becomes UDP/4500 carrying ESP. That changes what middleboxes see:

  • Stateful firewalls now need UDP state for the flow.
  • Conntrack timers now matter (UDP is “connectionless,” but stateful NAT pretends otherwise).
  • Some security devices inspect UDP/4500 poorly or rate-limit it aggressively.

The quiet killer: NAT mapping timers and keepalives

NATs forget UDP mappings quickly. Thirty seconds is common. Some are even shorter under load. IPsec tunnels, meanwhile, can be idle for minutes—especially “backup” or “management-only” site-to-site links. Result: the mapping evaporates, the peer keeps sending encrypted UDP/4500 packets into the void, and nobody tells you until the next packet matters.

The fix is usually a keepalive or DPD/heartbeat tuning. Not “make the crypto stronger.” Not “rekey every 5 minutes.” Keep the NAT mapping alive, or accept that the first packet after idle will be sacrificed.

Why fragmentation and MTU issues show up more with NAT-T

NAT-T adds UDP overhead. IPsec adds ESP overhead. If you were already tight on MTU (MPLS, PPPoE, GRE, cloud VNets, whatever), NAT-T pushes you over the edge.

When PMTUD is blocked (ICMP filtered), large packets vanish. Small pings work. SSH works. File transfers hang. Database connections stall under load. This is why “it works for me” often means “I only tested with 56 bytes.”

Joke #2: The only thing more optimistic than “it pings” is “it pings, so it’s not the network.”

One reliability quote, because ops has receipts

Hope is not a strategy. — Gen. Gordon R. Sullivan

In VPN terms: don’t hope NAT-T is fine because the tunnel says ESTABLISHED. Measure the data plane.

Fast diagnosis playbook

This is the order that finds real failures fast. It’s biased toward what breaks most often in production: filtering, NAT state, routing/policy, and MTU.

First: confirm what transport the tunnel is actually using

  • Is IKE on UDP/500 only, or did it switch to UDP/4500?
  • Is the data plane ESP (proto 50) or UDP/4500 encapsulated?

If you don’t know this, you’re troubleshooting blind. “Allow IPsec” is not a firewall rule; it’s a marketing phrase.

Second: prove bidirectional UDP/4500 reachability (not just “open”)

  • Packet capture on both peers, looking for outbound and inbound UDP/4500 packets.
  • Check that the NAT device maintains the mapping long enough (timers/keepalives).

Third: validate selectors/policies and routing for the protected subnets

  • Do the traffic selectors (local/remote subnets) match on both ends?
  • Is there a route that points protected subnets into the tunnel interface/policy?
  • Are you accidentally NATing the traffic that should be encrypted?

Fourth: if “some traffic works,” go straight to MTU/MSS and fragmentation

  • Test with DF set and larger payload sizes.
  • Look for ICMP “fragmentation needed” being blocked.
  • Clamp MSS for TCP if needed.

Fifth: only then go spelunking in crypto proposals and rekey timers

Yes, proposal mismatches happen. But NAT-T failures are often post-negotiation and look like “crypto is fine, data is dead.” Treat the symptoms honestly.

Practical tasks: commands, outputs, and decisions (12+)

These are the tasks I actually run when a site-to-site IPsec tunnel is “up” but behaving like it’s haunted. Each includes a realistic command, sample output, what it means, and the decision you make.

Task 1: Confirm IKEv2 SAs and whether NAT-T is in use (strongSwan)

cr0x@server:~$ sudo swanctl --list-sas
IKE SAs:
corp-vpn[3]: ESTABLISHED 12 minutes ago, 203.0.113.10[gw-a]...198.51.100.20[gw-b]
corp-vpn[3]: IKEv2, rekeying in 46 minutes
corp-vpn[3]: IKE proposal: AES_GCM_16_256/PRF_HMAC_SHA2_256/ECP_256
corp-vpn{7}:  INSTALLED, TUNNEL, reqid 1, ESP in UDP SPIs: c3b8a9d2_i c9b6a331_o
corp-vpn{7}:  10.10.0.0/16 === 10.20.0.0/16

What it means: “ESP in UDP” confirms NAT-T encapsulation on UDP/4500 for the data plane.

Decision: Ensure UDP/4500 is allowed end-to-end and that NAT mapping timers won’t expire. If UDP/4500 isn’t explicitly permitted, fix that before touching proposals.

Task 2: Check for NAT detection messages in logs (strongSwan/charon)

cr0x@server:~$ sudo journalctl -u strongswan --since "30 min ago" | egrep -i "NAT|4500|encap|DPD" | tail -n 20
Feb 04 09:12:31 gw-a charon[1123]: 11[IKE] local host is behind NAT, sending keep alives
Feb 04 09:12:31 gw-a charon[1123]: 11[IKE] remote host is behind NAT
Feb 04 09:12:31 gw-a charon[1123]: 11[IKE] switching to NAT-T
Feb 04 09:12:41 gw-a charon[1123]: 11[IKE] sending keep alive to 198.51.100.20[4500]

What it means: NAT was detected; the daemon switched to NAT-T and is sending keepalives.

Decision: If traffic still dies, the keepalives may not be frequent enough, or the firewall/NAT isn’t allowing inbound replies on UDP/4500.

Task 3: Verify local listening sockets (is the daemon bound properly?)

cr0x@server:~$ sudo ss -ulnp | egrep ':500|:4500'
UNCONN 0      0            0.0.0.0:500       0.0.0.0:*    users:(("charon",pid=1123,fd=10))
UNCONN 0      0            0.0.0.0:4500      0.0.0.0:*    users:(("charon",pid=1123,fd=11))

What it means: The IKE daemon is listening on UDP/500 and UDP/4500.

Decision: If 4500 isn’t listening, NAT-T can’t work. Fix the IPsec stack config or verify kernel capabilities/modules.

Task 4: Check firewall rules for UDP/500 and UDP/4500 (nftables)

cr0x@server:~$ sudo nft list ruleset | sed -n '/table inet filter/,/}/p' | egrep -n "udp dport (500|4500)|ip protocol esp|drop"
24: udp dport { 500, 4500 } accept
31: ip protocol esp accept
78: counter drop

What it means: This host firewall allows IKE and NAT-T, plus raw ESP. Good.

Decision: If you see UDP/500 allowed but not UDP/4500, add 4500. If you see drops incrementing, capture and refine rules.

Task 5: Confirm packets are arriving on UDP/4500 (tcpdump)

cr0x@server:~$ sudo tcpdump -ni eth0 udp port 4500 -c 10
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), snapshot length 262144 bytes
09:14:02.112233 IP 198.51.100.20.4500 > 203.0.113.10.4500: UDP, length 92
09:14:12.112998 IP 203.0.113.10.4500 > 198.51.100.20.4500: UDP, length 92
09:14:22.113554 IP 198.51.100.20.4500 > 203.0.113.10.4500: UDP, length 300

What it means: Bidirectional UDP/4500 traffic exists. At least the transport path is alive.

Decision: If you only see outbound or only inbound, suspect firewall/NAT asymmetry or upstream filtering. Escalate to the network edge with captures as evidence.

Task 6: Confirm that protected traffic is being encrypted (XFRM state)

cr0x@server:~$ sudo ip -s xfrm state
src 203.0.113.10 dst 198.51.100.20
	proto esp spi 0xc9b6a331 reqid 1 mode tunnel
	replay-window 32 flag af-unspec
	aead rfc4106(gcm(aes)) 0x... 256 bits
	anti-replay context: seq 0x0000002a, oseq 0x0
	lifetime current: 780s, bytes 12480, packets 104
src 198.51.100.20 dst 203.0.113.10
	proto esp spi 0xc3b8a9d2 reqid 1 mode tunnel
	lifetime current: 780s, bytes 9800, packets 91

What it means: Packet and byte counters are increasing. Encryption is happening in the kernel.

Decision: If counters stay at zero while you generate traffic, your selectors/routing/policy are wrong (traffic isn’t matching the IPsec policy), or packets are blocked before hitting XFRM.

Task 7: Verify policy selectors (XFRM policy)

cr0x@server:~$ sudo ip xfrm policy
src 10.10.0.0/16 dst 10.20.0.0/16
	dir out priority 3750 ptype main
	tmpl src 203.0.113.10 dst 198.51.100.20 proto esp reqid 1 mode tunnel
src 10.20.0.0/16 dst 10.10.0.0/16
	dir in priority 3750 ptype main
	tmpl src 198.51.100.20 dst 203.0.113.10 proto esp reqid 1 mode tunnel

What it means: The kernel expects traffic between these subnets to be tunneled.

Decision: If your real networks are /24s but policy is /16 (or vice versa), you’ll get weird partial failures. Fix selectors to match the actual routes and intended encryption domain.

Task 8: Confirm routing sends protected traffic to the right place

cr0x@server:~$ ip route get 10.20.5.10 from 10.10.5.10
10.20.5.10 from 10.10.5.10 dev eth0  src 203.0.113.10  uid 0
    cache

What it means: On policy-based IPsec, traffic often still routes “normally” (e.g., out eth0) and gets picked up by XFRM policy. That’s fine.

Decision: If the route points somewhere unexpected (wrong egress interface, wrong source IP), fix routing/source selection. Wrong source IP can break NAT detection and selector matching.

Task 9: Generate traffic and watch counters move (ping + XFRM)

cr0x@server:~$ ping -c 3 10.20.5.10
PING 10.20.5.10 (10.20.5.10) 56(84) bytes of data.
64 bytes from 10.20.5.10: icmp_seq=1 ttl=63 time=22.3 ms
64 bytes from 10.20.5.10: icmp_seq=2 ttl=63 time=21.9 ms
64 bytes from 10.20.5.10: icmp_seq=3 ttl=63 time=22.1 ms

--- 10.20.5.10 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2003ms
rtt min/avg/max/mdev = 21.9/22.1/22.3/0.2 ms

What it means: Data plane works for small packets.

Decision: Immediately test MTU with DF and larger sizes. “Small ping works” is not success; it’s a trap.

Task 10: Test MTU/fragmentation with DF set

cr0x@server:~$ ping -M do -s 1372 -c 3 10.20.5.10
PING 10.20.5.10 (10.20.5.10) 1372(1400) bytes of data.
ping: local error: message too long, mtu=1392

--- 10.20.5.10 ping statistics ---
3 packets transmitted, 0 received, +3 errors, 100% packet loss, time 2034ms

What it means: Your effective path MTU is smaller than expected (here 1392). IPsec/NAT-T overhead reduced it. If ICMP is blocked elsewhere, you might see silent drops instead of a local error.

Decision: Clamp TCP MSS (for TCP-heavy apps) and/or reduce interface MTU on tunnel path. If you don’t control intermediate networks, MSS clamping is often the pragmatic fix.

Task 11: Check TCP MSS clamping rules (iptables example)

cr0x@server:~$ sudo iptables -t mangle -S | egrep "TCPMSS|clamp-mss-to-pmtu"
-A FORWARD -p tcp -m tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu

What it means: MSS clamping is enabled on forwarded TCP SYN packets.

Decision: If you have MTU blackholes and can’t fix ICMP, add MSS clamping on the gateway and re-test file transfers and TLS handshakes.

Task 12: Validate that NAT is not being applied to protected subnets (iptables NAT table)

cr0x@server:~$ sudo iptables -t nat -S POSTROUTING
-P POSTROUTING ACCEPT
-A POSTROUTING -s 10.10.0.0/16 -o eth0 -j MASQUERADE

What it means: This would NAT all traffic from 10.10.0.0/16 leaving eth0, including traffic that should be encrypted to 10.20.0.0/16.

Decision: Add a NAT exemption rule for the VPN destination before MASQUERADE, or tighten the MASQUERADE rule to exclude the protected remote subnet.

Task 13: Inspect conntrack timeouts for UDP/4500

cr0x@server:~$ sudo sysctl net.netfilter.nf_conntrack_udp_timeout net.netfilter.nf_conntrack_udp_timeout_stream
net.netfilter.nf_conntrack_udp_timeout = 30
net.netfilter.nf_conntrack_udp_timeout_stream = 180

What it means: UDP “connection” state expires fast (30s for unreplied flows). That can kill idle NAT-T tunnels if keepalives are too sparse.

Decision: Prefer configuring IKE keepalives/DPD; adjusting conntrack timeouts can help but affects the whole box and may have unintended consequences.

Task 14: Verify rekey/DPD settings are not causing self-inflicted flaps (strongSwan status)

cr0x@server:~$ sudo swanctl --list-conns | sed -n '/corp-vpn/,/}/p'
corp-vpn: IKEv2, dpd_delay=30s, dpd_timeout=120s, rekey_time=1h
  local:  203.0.113.10
  remote: 198.51.100.20
  local_ts: 10.10.0.0/16
  remote_ts: 10.20.0.0/16

What it means: DPD is configured. Rekey interval is reasonable.

Decision: If you see super-aggressive DPD (e.g., delay 5s, timeout 15s) across a lossy WAN, you’ll flap your own tunnel. Tune for the link you actually have, not the one you wish you had.

Task 15: Prove whether UDP/4500 is blocked upstream (nmap UDP scan with caution)

cr0x@server:~$ sudo nmap -sU -p 500,4500 198.51.100.20
Starting Nmap 7.94 ( https://nmap.org ) at 2026-02-04 09:22 UTC
Nmap scan report for 198.51.100.20
Host is up (0.021s latency).

PORT     STATE         SERVICE
500/udp  open|filtered isakmp
4500/udp open|filtered nat-t-ike

Nmap done: 1 IP address (1 host up) scanned in 2.49 seconds

What it means: UDP scan results are ambiguous (“open|filtered” is common). It doesn’t prove it’s open, but it tells you the host is reachable and not sending back ICMP port-unreachable.

Decision: Use tcpdump as the source of truth. If you see your packets leave but never see replies, escalate with captures.

Common mistakes: symptom → root cause → fix

1) “IKE SA established, but no traffic passes”

Symptom: Control plane comes up. Data plane counters stay at zero.

Root cause: UDP/4500 blocked (or ESP blocked when NAT-T is off). Or selectors don’t match, so packets never hit XFRM.

Fix: Confirm “ESP in UDP” (or not) in SA output, then allow UDP/4500 bidirectionally. Validate XFRM policy selectors match real subnets and that NAT exemptions exist.

2) “Works for a while, then dies after idle”

Symptom: After 5–30 minutes of inactivity, the first new flow times out; tunnel may recover later.

Root cause: NAT mapping expiration for UDP/4500; keepalives/DPD too slow; upstream UDP state timing out.

Fix: Enable NAT keepalives / IKEv2 liveness checks tuned to be more frequent than the shortest NAT timeout in the path. If you can’t know the timeout, assume 20–30 seconds and design for that.

3) “One direction works, the other doesn’t”

Symptom: Site A can reach Site B, but not vice versa (or only some subnets work).

Root cause: Asymmetric routing, missing return route, overlapping subnets, policy mismatch, or NAT on only one side without symmetric allowances.

Fix: Compare traffic selectors on both ends; check routing tables; ensure no overlap; verify firewall rules for both directions; confirm packets are encapsulated and seen on both ends with tcpdump.

4) “Ping works, SMB/HTTPS/file transfers hang”

Symptom: Small packets succeed; larger payloads stall or reset.

Root cause: MTU blackhole due to IPsec + NAT-T overhead; PMTUD broken; ICMP filtered; fragmentation mishandled by NAT.

Fix: Test with DF pings, clamp TCP MSS, and/or set lower MTU on relevant interfaces. Also allow necessary ICMP types if your security posture permits it.

5) “Tunnel flaps during rekey, especially under NAT”

Symptom: Periodic drops aligned with rekey timers; logs show retransmits and CHILD SA churn.

Root cause: Rekey collisions, poor NAT stability, strict firewall pinholing, or aggressive DPD interacting with transient packet loss.

Fix: Stagger rekey times, avoid ultra-short lifetimes, tune DPD, and ensure UDP/4500 is not rate-limited or subject to short conntrack timers.

6) “Everything breaks after changing ISP/modem/router”

Symptom: Same configs, new access device, now NAT-T fails.

Root cause: New device does symmetric NAT, endpoint-independent mapping changed, or it ‘optimizes’ UDP aggressively. Some also block UDP/4500 by default.

Fix: Put the VPN gateway on a public IP or true bridge mode; otherwise tune keepalives and verify UDP/4500 pass-through explicitly.

7) “Cloud VPN says connected; on-prem sees no inbound”

Symptom: Cloud side is happy; on-prem shows IKE up; data plane inbound is missing.

Root cause: On-prem edge firewall permits outbound but not inbound UDP/4500; or NAT device doesn’t preserve ports; or security group rules incomplete.

Fix: Validate symmetric rules on both ends. Capture on the on-prem WAN interface to prove whether inbound encapsulated traffic arrives.

Three corporate mini-stories from the trenches

Mini-story 1: The incident caused by a wrong assumption

They had a site-to-site VPN between a small office and a central DC. It had run for years. Then the office moved floors and got a “simple” network refresh: a new ISP circuit, a new edge firewall, and a tidy VLAN redesign that made the diagrams look like a textbook.

Monday morning, the tunnel came up. Their monitoring saw IKE established and declared victory. But the ERP client traffic was dead. The vendor’s first response was the usual: “Looks like your firewall.” The network team’s first response was also the usual: “Tunnel is up, so it’s not us.” That stalemate burned half a day.

The wrong assumption was subtle: they assumed that because UDP/500 was permitted and IKE negotiated, NAT-T would “just work.” On the new firewall, UDP/4500 was not allowed inbound by default. The device did allow outbound. So the office could initiate, but the DC could not reliably send back encapsulated traffic after rekeys and idle periods.

What fixed it wasn’t heroics. It was two packet captures and one uncomfortable meeting. A tcpdump on the office WAN showed outbound UDP/4500 leaving. A capture on the DC edge showed nothing arriving. Once you have that evidence, the debate ends. They added symmetric UDP/4500 rules, enabled keepalives on the office gateway, and the tunnel stopped lying.

Mini-story 2: The “optimization” that backfired

A different company had a global mesh of VPNs, and someone got ambitious about “reducing noise.” They noticed periodic NAT keepalive packets and DPD probes and decided to lengthen timers—less chatter, less CPU, fewer logs. It sounded responsible. It also broke reality.

Their edge NAT devices, particularly in smaller sites, had aggressive UDP timeouts. With longer keepalive intervals, NAT mappings expired during quiet periods. The next burst of business traffic hit a dead mapping. The remote peer retransmitted. DPD eventually declared the peer dead. Rekey timing drifted. From the application side, it looked like random 30–90 second outages a few times a day.

Because the tunnel often healed itself, the first instinct was to blame the ISP or “the cloud.” But packet captures showed the remote gateway dutifully sending UDP/4500 packets to an address/port combination the NAT no longer forwarded. Nothing on the outside was “down.” The state was gone.

The fix was to undo the optimization and accept a small trickle of keepalives as the cost of doing business behind NAT. They also set a policy: if you change liveness timers, you must validate against the shortest NAT timeout in the fleet, not the best one. The noisy tunnel became the reliable tunnel. In ops, boring is a feature.

Mini-story 3: The boring but correct practice that saved the day

A finance org had strict change control and an annoying habit: every network change required a pre-change capture and a post-change capture for critical links. Engineers grumbled. Nobody likes process theater. But this one turned out to be real theater: the kind where you catch the villain before the third act.

They planned a firewall upgrade at a remote site. Before the change, they captured 60 seconds of traffic on the WAN interface and saved it with the change record. After the upgrade, the tunnel came up—but the call center app started failing on large responses. Small tests passed. The vendor said “not us.” The app team said “network.” You know the chorus.

Because they had before/after pcaps, they could compare. The post-upgrade capture showed UDP/4500 packets larger than before, and it showed fragmentation behavior changed. The new firewall was dropping IP fragments more aggressively on the WAN side. That’s not an IKE problem; that’s a data-plane reality problem.

The fix was equally boring: clamp TCP MSS and adjust the interface MTU to account for IPsec/NAT-T overhead. The tunnel didn’t just recover—it stopped generating weird, intermittent failures. The process that everyone mocked produced the shortest outage report of the quarter.

Checklists / step-by-step plan

Build it right (new site-to-site behind NAT)

  1. Decide the model: If you can avoid NAT, avoid NAT. Put at least one peer on a stable public IP when possible.
  2. Open the right traffic: Allow UDP/500 and UDP/4500 bidirectionally. If you ever run without NAT-T, also allow ESP (IP proto 50). Be explicit.
  3. Pick sane lifetimes: Don’t rekey every few minutes unless you enjoy pager fatigue.
  4. Enable liveness: Configure DPD and NAT keepalives. Tune for the worst NAT timeout you expect, not the best.
  5. Plan MTU: Assume overhead. Validate with DF tests. Implement MSS clamping if you don’t control ICMP end-to-end.
  6. Write down selectors: Local/remote subnets, and verify they don’t overlap with any other site.
  7. Implement NAT exemptions: Traffic destined for the VPN should not be source-NATed before encryption.
  8. Add monitoring that measures data plane: Not just “tunnel up.” Measure successful flows, byte counters, and latency/jitter.

Change it without breaking it (firewall upgrades, ISP swaps, subnet changes)

  1. Capture UDP/500 and UDP/4500 before change (30–60 seconds during real traffic).
  2. Record current SA state, selectors, and MTU/MSS settings.
  3. After change, confirm listening ports and firewall rules first.
  4. Re-test with small ping and DF ping.
  5. Verify XFRM counters or vendor-equivalent counters increase when you generate traffic.
  6. Only then adjust timers/proposals if negotiation fails.

When it’s on fire (incident response checklist)

  1. Is it negotiating on UDP/500? Is it switching to UDP/4500?
  2. Do both sides see inbound UDP/4500 in a capture?
  3. Are byte counters increasing on the SAs?
  4. Do selectors match the real subnets? Any overlaps?
  5. Is NAT exemption present? Any new MASQUERADE rules?
  6. Can large DF pings pass? If not, clamp MSS now and schedule deeper MTU work.
  7. Check for recent ISP/CPE changes that introduced double NAT or new filtering.

Interesting facts and history you can weaponize

  • NAT wasn’t part of the original IP design. It became popular in the 1990s as a pragmatic response to IPv4 exhaustion and addressing policies.
  • Classic IPsec ESP doesn’t have ports. NAT devices typically track flows using ports, which is why ESP (IP protocol 50) is inherently NAT-hostile.
  • NAT-T standardized the “ESP in UDP” approach. The core idea is simple: wrap ESP so NAT can track it like any other UDP flow.
  • UDP/4500 is the conventional NAT-T port. UDP/500 is used for IKE; NAT-T commonly transitions to UDP/4500 after NAT detection.
  • IKEv2 improved message structure and reliability. Compared to IKEv1, IKEv2 is less baroque and tends to behave better under packet loss—but it still depends on the network path behaving.
  • Some NATs are “symmetric,” and that matters. Symmetric NAT can break assumptions about port preservation and inbound reachability, especially when multiple tunnels or peers share an address.
  • PMTUD failures are older than NAT-T. But NAT-T increases overhead, making latent MTU problems show up more frequently and more painfully.
  • DPD and keepalives are operational tools, not optional niceties. They exist because middleboxes time out state and because “silent failure” is common on the internet.
  • Cloud VPNs often hide complexity behind “connected” status. That status usually reflects IKE control-plane health, not whether your specific subnets and routes are passing real traffic.

FAQ

1) If IKEv2 shows ESTABLISHED, why can’t I pass traffic?

Because control plane and data plane are different. IKE can succeed on UDP/500 while UDP/4500 or ESP is blocked, selectors don’t match, routes are wrong, or MTU blackholes eat your larger packets.

2) Do I always need to open ESP (IP protocol 50)?

If you’re always using NAT-T, the data plane is UDP/4500, not raw ESP. But many environments can switch modes depending on NAT detection or configuration, so permitting ESP can be helpful. The real answer: verify what your peers actually use and write firewall rules accordingly.

3) Can I run NAT-T even if there is no NAT?

Often yes, depending on the implementation. But forcing NAT-T everywhere can add overhead and expose you to UDP-specific filtering/conntrack behavior. Use it when you need it; don’t use it as superstition.

4) Why does the tunnel die only after being idle?

NAT and stateful firewalls time out UDP state. Without frequent keepalives, the mapping disappears. Your next packet goes to a port mapping that no longer exists.

5) What keepalive interval should I use?

Less than the shortest NAT timeout you expect on the path. In mixed enterprise environments, assuming ~20–30 seconds is common. The “right” value is one that keeps mappings alive without causing needless churn. If you’re guessing, guess conservative and verify with measurements.

6) Why do small pings work but applications fail?

MTU/fragmentation. NAT-T + IPsec overhead reduces the effective MTU. If PMTUD is broken, large packets vanish. Fix with MSS clamping and/or MTU tuning, and consider allowing necessary ICMP types.

7) What’s the fastest way to prove UDP/4500 is blocked?

Capture on both ends. If you see outbound UDP/4500 leaving one peer and nothing arriving at the other, the path is filtering or misrouting. Packet captures beat opinions.

8) Does double NAT matter?

Yes. It can change port mappings, shorten timers, and introduce symmetric NAT behavior. If you can’t remove double NAT, you typically need more aggressive keepalives and stricter firewall symmetry.

9) Are aggressive rekey timers good for security?

Security is not improved by making the tunnel unusable. Reasonable lifetimes with stable behavior beat constant rekeys that trigger packet loss, collisions, and flaps—especially behind NAT.

10) How should I monitor a site-to-site IPsec tunnel properly?

Monitor data-plane success: periodic synthetic transactions between real hosts/subnets, plus SA byte counters and retransmit/DPD events. “IKE is up” is necessary, not sufficient.

Next steps you should actually do

  1. Inventory your tunnels and record for each one: whether it uses NAT-T (UDP/4500), what subnets are protected, and what keepalive/DPD timers are set.
  2. Make UDP/4500 rules explicit on every firewall between peers. “IPsec allowed” is not an audit-friendly statement.
  3. Add one data-plane check per tunnel: a small ping, a DF ping near MTU, and a TCP transaction (HTTPS or similar). Alert on failure, not on “SA missing.”
  4. Fix MTU proactively: implement MSS clamping on gateways where you don’t control ICMP and where tunnels cross unpredictable networks.
  5. Stop ‘optimizing’ away keepalives unless you’ve measured NAT timeouts end-to-end. If you must reduce chatter, do it with evidence and rollback plans.
  6. When incidents happen, lead with captures. A 30-second pcap on each WAN interface ends arguments faster than any meeting invite.

If you do these, NAT-T becomes a boring detail again—which is exactly where it belongs.

← Previous
Disable BitLocker Before Reinstall? The Step People Skip
Next →
Disable Legacy Protocols (NTLMv1, LLMNR): What Breaks and How to Replace

Leave a comment