NAT Traversal (NAT-T) » History » Version 9

« Previous - Version 9/13 (diff) - Next » - Current version
Tobias Brunner, 05.07.2017 14:41
Some updates and clarifications

NAT Traversal (NAT-T)

The IKEv2 protocol includes NAT traversal (NAT-T) in the core standard, but it's optional to implement. strongSwan implements it and does not require any special configuration. The NAT_DETECTION_SOURCE/DESTINATION_IP notifications included in the IKE_SA_INIT exchange indicate the peer's NAT-T capability and allow detecting which peer, if any, is behind a NAT device. If a NAT situation is detected, the client switches to UDP port 4500 to send the IKE_AUTH request (only if it used port 500 initially, see below regarding custom ports) and UDP encapsulation will be activated for IPsec SAs.

NAT-T cannot be disabled in the charon IKE daemon. If you don't like the automatic port floating to UDP/4500 due to the MOBIKE protocol, which happens even if no NAT situation exists, then you can disable MOBIKE by disabling the mobike option in your connection definition.

UDP Encapsulation of ESP

Because ESP packets are unidirectional NAT devices can't map them like they do with e.g. TCP/UDP packets by using the ports in those headers. Some NAT devices have a feature, often called something like "IPsec passthrough", that detects IKE traffic from a single host behind the NAT and will forward incoming plain ESP packets to that host. But that won't work with multiple clients behind the same NAT that use the same server. To allow multiple clients UDP encapsulation is used. Adding a UDP header to the ESP packets allows NAT devices to treat them like the IKE packets (or any other UDP packets) and to maintain port mappings to forward the packets from/to the correct hosts behind the NAT.

The UDP encapsulated ESP packets are sent on the same ports used for IKE traffic. To distinguish them from IKE packets the latter are modified so they contain four zero bytes right after the UDP header where the SPI is located in ESP packets (known as "non-ESP marker"). This means that the UDP socket/port (4500 by default) has to handle traffic differently than the default IKE socket/port. This has some implications when using a custom server port (see below).

UDP encapsulation may also be forced, even if no NAT situation is detected, by using the forceencaps and encap options in ipsec.conf and swanctl.conf, respectively. If enabled, the daemon will send a fake NAT_DETECTION_SOURCE_IP notify payload so it looks to the peer as if there is a NAT situation.

NAT-T Keepalives

strongSwan starts sending keepalive packets if it is behind a NAT to keep the mappings in the NAT device intact. The interval for these small packets (a single 0xff byte after the UDP header) may be configured with the charon.keep_alive strongswan.conf option (set to 0 to disable sending keepalives, e.g. behind a static DNAT aka port forwarding).

Custom Server Ports

As described above, if UDP encapsulation is used the ESP packets are sent on the ports already used for IKE traffic. Because there is no port switch when using a custom port (for simplicity, the client uses only one port, configured either in rightikeport or remote_port), and due to the addition of non-ESP markers when using ports != 500, traffic must usually go via NAT-T port. Therefore, when setting a custom port on the server the right option is charon.port_nat_t, the charon.port option is not relevant in this scenario (i.e. that socket/port will not be used). When sending traffic to that port a non-ESP marker has to be added. strongSwan adds one if neither source, nor destination port is 500. This means the client can't use port 500 for its default IKE socket, so it will already add a non-ESP marker when sending the initial IKE_SA_INIT request. This can be achieved by setting charon.port on the client to either 0 (so a random port is allocated) or any number != 500 if that port is not used by any other process. The client will, however, switch to the second source port configured via charon.port_nat_t if a NAT is detected or MOBIKE is enabled, so setting both to 0 usually makes most sense for mobile clients that connect to a custom server port (but using port 4500 as source is usually also not a problem).


Before strongSwan 5.0.0, NAT discovery and traversal for IKEv1 had to be enabled by setting nat_traversal=yes in the config setup section of ipsec.conf. Otherwise, strongSwan 4.x's IKEv1 pluto daemon would not accept incoming IKE packets with a UDP source port different from 500. Since 5.0.0 IKEv1 traffic is handled by the charon daemon, which supports NAT traversal according to RFC 3947 (and some of its early drafts) without having to enable it explicitly (it can't be disabled either, though).