skip to content

In IKEv2, how do the NAT_DETECTION_SOURCE_IP and NAT_DETECTION_DESTINATION_IP payloads reveal a NAT, and what changes once one is found?

level: middleimportance: must knowfreq 25%

answer

  1. compare what was sent with what arrived
  2. hash of SPIs, address and port
  3. source mismatch versus destination mismatch
  4. IKE_AUTH already on 4500

basics

~20 s

Each IKEv2 peer sends SHA-1 hashes of the SPIs with its source and destination address and port in IKE_SA_INIT. A mismatch reveals a translator and which side is behind it; IKE and ESP then move to UDP 4500.

solid answer

~40 s

In `IKE_SA_INIT` both peers include a `NAT_DETECTION_SOURCE_IP` notify, a SHA-1 hash of the SPIs, the source address and the source port they sent from, and a `NAT_DETECTION_DESTINATION_IP` notify, the same hash over the address and port they sent to. The receiver recomputes the hashes from the IP and UDP headers that actually arrived. If no source hash matches, the **sender** is behind a NAT; if the destination hash does not match, the **receiver** is, and it should start sending NAT-keepalives. When a mismatch is found the initiator MUST move all further IKE and ESP for that IKE SA to UDP `4500`, so `IKE_AUTH` already travels there with the four-byte non-ESP marker, and both peers MUST then UDP-encapsulate ESP.

go deeper

for a junior

Recall that IKEv2 detects a NAT during its first exchange by comparing hashed addresses and ports, and that the connection then moves to UDP port 4500.

for a middle

Explain both notifications, what each hash covers, how a source mismatch and a destination mismatch are read, and why IKE_AUTH already travels on port 4500 with the non-ESP marker.

for a senior

Use the detection result in troubleshooting: which side should send keepalives, why replies must go to the translated port, and why a firewall passing only UDP 500 lets IKE_SA_INIT through and stalls at IKE_AUTH.

for a principal

Weigh starting every negotiation on 4500 against detecting first, and judge how much the weak address hiding in the hashes matters for remote users whose inside addresses are private anyway.

## The idea: compare what was sent with what arrived A NAT rewrites addresses and ports in the IP and UDP headers but cannot touch what the sender wrote inside the IKE message. IKEv2 (RFC 7296 §2.23) uses that asymmetry. Each peer writes down, inside its first message, where it thinks the packet comes from and where it is going. The receiver compares that statement with the headers it actually received. If they disagree, something on the path translated the packet. ## The two notifications Both the initiator and the responder put two **Notify** payloads in their `IKE_SA_INIT` message, after the nonces (`Ni`/`Nr`) and before any `CERTREQ`: | Notify (type number) | Hash input | What a mismatch means at the receiver | |---|---|---| | `NAT_DETECTION_SOURCE_IP` (16388) | SPIs, sender's source address, source port | The **sender** is behind a NAT | | `NAT_DETECTION_DESTINATION_IP` (16389) | SPIs, destination address, destination port | The **receiver itself** is behind a NAT | Each value is a **SHA-1** digest of the IKE SPIs in header order, the IP address and the port. A sender with several interfaces that does not know which one will be used MAY include several source notifications; a NAT is concluded only if none of them matches. ## Reading the result, step by step Take a laptop at `192.168.1.10` behind a home router whose public address is `198.51.100.7`, talking to a gateway at `203.0.113.5`: 1. The laptop sends `IKE_SA_INIT` from `192.168.1.10:500` to `203.0.113.5:500`, hashing those values into its two notifications. 2. The router rewrites the source to, say, `198.51.100.7:61022`. 3. The gateway hashes the source it sees and finds no match: **the initiator is behind a NAT**. The destination hash the laptop sent matches the gateway's own address and port, so the gateway itself is not translated. 4. The gateway's reply carries its own pair of hashes; the laptop finds its destination hash does not match, because the gateway hashed `198.51.100.7:61022`. The laptop learns **it is the one behind the NAT** and SHOULD start sending keepalives. 5. Because a mismatch was seen, the initiator MUST tunnel all further IKE and ESP for this IKE SA over **UDP 4500**. `IKE_AUTH` goes from port `4500` to port `4500`, prefixed by four zero bytes, and the router gives it a fresh mapping such as `198.51.100.7:61023`. 6. The gateway replies to the port the packet came from; RFC 7296 requires IKE to accept requests from any port and answer to the port they came from, because NATs rewrite ports. 7. Once a NAT is detected, **both peers MUST UDP-encapsulate ESP** for the Child SAs. ## Why hashes and not plain addresses - The payload must survive translation untouched, and it must not hand an inside address to every network it crosses; RFC 7296 says the hash is used in an attempt to hide internal addresses. - Including the SPIs makes each hash specific to this negotiation, so it cannot be precomputed once for every exchange. - The hiding is weak. RFC 7296's security considerations note that IPv4 has only 32 bits of address space, the port is usually 500 and the SPIs are visible in the packet, so an observer can recover the inside address by trying candidates. ## Why move to 4500 at all - Some NATs treat port `500` specially, for example by not translating it or by tracking IKE cookies, which breaks with several clients; RFC 7296 says NATs should not treat port 4500 specially. - IKE and ESP share one port, so one mapping, one firewall rule and one set of keepalives serve both. - An initiator may start on 4500 from the first message; then there is nothing left to move. ## History and status IKEv1 did the same job with a `NAT-D` payload (payload type 20) and a vendor ID announcing support, defined in RFC 3947, and floated to 4500 in Main Mode's fifth message. IKEv1 is deprecated by RFC 9395, so new deployments use the IKEv2 notifications. Support for NAT traversal is optional in RFC 7296; the requirements above bind only implementations that support it, and one that does not MAY reject the connection when it sees a mismatch.

  • Does a NAT_DETECTION mismatch prove an attacker tampered with the packet?
    No. A mismatch is the normal signature of address or port translation, and the specified reaction is to enable NAT traversal. The notifications are unauthenticated hashes in `IKE_SA_INIT`; peer authentication happens in `IKE_AUTH`, which protects the exchange as a whole. An implementation without NAT traversal support MAY simply reject the attempt.
  • Why does the side behind the NAT, not the other, take on sending keepalives?
    The mapping lives in that side's NAT and only refreshes when packets leave from inside. A destination-hash mismatch tells a peer that its own address was translated, which is why RFC 7296 says that peer SHOULD start keepalives as RFC 3948 defines them.

saying these in an interview costs you the question

  • NAT detection happens in IKE_AUTH, after the peers authenticate.
  • The NAT_DETECTION payloads carry the inside IP address in clear text.
  • A source-hash mismatch means the receiver is the one behind the NAT.
  • After detecting a NAT, IKE stays on port 500 and only ESP moves.
  • A hash mismatch means the packet was forged, so the exchange is aborted.