Bug #731

NAT mapping update job fails when server is behind a 1:1 NAT

Added by Eric Severance over 7 years ago. Updated over 7 years ago.

Target version:
Start date:
Due date:
Estimated time:
Affected version:


My VPN client is behind a NAT that sometimes expires the port mappings for my VPN connection. This results in my VPN server detecting the port mapping changes and logging the following message:
NAT mappings of ESP CHILD_SA with SPI c266d4bf and reqid {1} changed, queuing update job

My strongSwan v5.2.0 server is running on Google Compute Engine (GCE). Virtual machines on GCE are assigned a private,, IP address on eth0. When a public/external IP address is allocated to the virtual machine, the GCE one-to-one NAT forwards packets to the virtual machine, changing only the IP address (to the private IP) and leaving the ports unmodified.

When strongSwan detects that the server host is behind a NAT, it will not actually update the IPSec SA with the kernel. This results in many "NAT mappings of ESP CHILD_SA with SPI c266d4bf and reqid {1} changed, queuing update job" messages, one each time the client sends a packet, and the NAT mappings never actually get updated.

I believe this is a bug. strongSwan should update the NAT mappings if the server is behind a one-to-one NAT that does not modify the ports. To test this, I patched libcharon/processing/jobs/update_sa_job.c to not check if the server is behind a NAT and to force the ike_sa->update_hosts(..) method to update the mappings. Now, when my client port changes, the server is able to update the SA mappings in the kernel.

Please allow libcharon to update NAT mappings when the server is behind a one-to-one NAT.

strongswan_nat_hack_workaround.patch (922 Bytes) strongswan_nat_hack_workaround.patch Example hack/patch to force NAT mapping updates. Eric Severance, 09.10.2014 20:03


#1 Updated by Tobias Brunner over 7 years ago

  • Status changed from New to Feedback
  • Assignee set to Tobias Brunner

I believe this is a bug.

It's not technically a bug, we just follow RFC 5996, section 2.23 quite strictly:

A host behind a NAT SHOULD NOT
do this type of dynamic address update if a validated packet has
different port and/or address values because it opens a possible
DoS attack (such as allowing an attacker to break the connection
with a single packet).

Thinking about this, it really seems only to be a problem for hosts behind dynamic NATs: If an attacker can capture a packet, change the source address/port and then send it so that it reaches the peer before the real packet arrives the remote endpoint would get updated to an incorrect address/port and the real packet would get dropped as retransmit (the peer would then send future packets to the wrong host or port). Theoretically this is fixed automatically by the first real packet from the remote host when the attacker stops the attack. But it's possible that the NAT mapping to the original endpoint already expired at that point and the connection stays broken as packets sent by the real host are then dropped by the NAT router. This could even happen after changing just one packet if the real host does not send any packets for a while, the NAT keepalives sent by the client would not keep the original mapping alive but the new, incorrect one.

For static NAT mappings (even port forwardings that modify ports) this is no problem as the endpoint stays open indefinitely.

We can't automatically detect whether the NAT is static or not, but we could probably use the absence of the COND_ORIGINAL_INITIATOR flag as heuristic as only a host behind a static NAT mapping can be reached by other peers directly. Another option would be to add a strongswan.conf option that allows updating remote addresses even when a NAT is detected (e.g. charon.update_peer_address_behind_nat).

I've implemented the first option in the update-remote-nat branch.

#2 Updated by Tobias Brunner over 7 years ago

  • Status changed from Feedback to Closed
  • Target version set to 5.2.1
  • Resolution set to Fixed

Also available in: Atom PDF