skip to content

Why does an IPsec AH packet fail its integrity check after crossing a NAT, when ESP traffic can be made to work?

level: middleimportance: must knowfreq 32%

answer

  1. what a translator rewrites
  2. immutable versus zeroed fields
  3. source address inside the ICV
  4. who holds the integrity key

basics

~20 s

AH's integrity check covers the IP source and destination addresses, which a NAT rewrites, so the receiver's recomputed ICV no longer matches and the packet is dropped. ESP's check excludes the outer header, so only ESP can be repaired.

solid answer

~50 s

The AH sender computes its ICV over the payload and the IP header fields RFC 4302 calls immutable — including the source and destination addresses — while zeroing the ones routers change, such as TTL, DSCP and the header checksum. Ordinary routing therefore leaves AH intact, but a NAT rewrites an address, and in transport mode a port-translating NAT also rewrites the TCP or UDP header that sits under AH's ICV. The NAT does not hold the SA's key, so it cannot recompute the ICV; the receiver's check fails and it MUST discard the packet. ESP's ICV starts at its SPI and never sees the outer header, so a rewritten address does not invalidate it. That is why RFC 3948 defines UDP encapsulation for ESP only, and why RFC 8221 keeps `ENCR_NULL` mandatory as the NAT-friendly route to integrity-only IPsec.

go deeper

for a junior

Remember the one-line cause: AH signs the IP addresses and a NAT changes them, so AH packets fail verification after translation.

for a middle

Walk through the field classes: immutable fields signed, mutable ones zeroed, and why an address change differs from a TTL change.

for a senior

Recognise the symptom of SAs established while AH traffic is silently discarded, and steer integrity-only requirements to ESP with NULL encryption.

for a principal

Weigh whether any outer-header guarantee justifies a protocol that forbids translation anywhere on the path, against what ESP plus policy checks already give.

## Why interviewers ask it "Why did NAT kill AH?" checks whether a candidate knows *which bytes* AH authenticates, not just that "AH and NAT don't mix". The answer is mechanical: AH signs fields a translator must change, and only the holder of the key can re-sign them. ## What AH puts under its ICV The sender computes the **Integrity Check Value** (`ICV`) with the keyed integrity algorithm of the security association (SA). RFC 4302 sorts every IPv4 base-header field into one of three classes: | Class | Fields | Treatment in the ICV | |---|---|---| | Immutable | Version, Internet Header Length, Total Length, Identification, Protocol, Source Address, Destination Address | included as sent | | Mutable but predictable | Destination Address when source routing is used | the final value is included | | Mutable | DSCP, ECN, Flags, Fragment Offset, TTL, Header Checksum | zeroed before computing | For IPv6 the immutable set is Version, Payload Length, Next Header and both addresses; DSCP, ECN, Flow Label and Hop Limit are zeroed. Everything **after** the AH header — in transport mode, the TCP or UDP header and data — is treated as immutable too. Zeroing is why a router decrementing TTL, a router remarking DSCP or a congested hop setting ECN does not break AH. Address translation is a different kind of change: it alters a field AH deliberately signs. ## What a NAT changes - A basic NAT rewrites the **source address** of outbound packets (or the destination of inbound ones) and recomputes the IPv4 **header checksum**. - A port-translating NAT also rewrites the **TCP or UDP port** and that header's checksum. The header checksum is zeroed for AH's ICV, so changing it is harmless. The address is not: it is an immutable field. And in transport mode the transport header lies after AH, inside the signed region. ## Following one packet 1. A host at 192.168.10.5 sends an AH-protected packet to 203.0.113.20. The ICV is computed over a header whose source address is 192.168.10.5. 2. The NAT rewrites the source to 198.51.100.7 and fixes the header checksum. It has no copy of the SA's integrity key, so it cannot produce a new ICV — and if it could, AH would offer no protection at all. 3. The receiver zeroes the mutable fields and recomputes the ICV over a header whose source is now 198.51.100.7. The result differs from the ICV in the packet. 4. RFC 4302: if ICV validation fails, the receiver MUST discard the datagram, and this is an auditable event. Every packet fails the same way. Because IKE runs over UDP, the key exchange itself can complete — so the symptom an operator sees is security associations that come up while no protected traffic gets through. ## Why ESP is different ESP's integrity computation covers the SPI, the sequence number, the payload and the ESP trailer. The IP header in front of ESP is not an input, so a translator rewriting the outer address leaves ESP's ICV valid. RFC 3715 (Informational) states the contrast directly: since ESP does not incorporate the IP addresses in its keyed integrity check, the issue that breaks AH "does not arise for ESP". ESP still has other difficulties at a translator — it has no ports for a port-translating NAT to rewrite, for example. Those are what NAT detection and UDP encapsulation repair; they are a separate subject. The point for AH is that **no repair was ever defined for it**: RFC 3948 specifies UDP encapsulation for ESP only, because AH's purpose — signing the addresses — is exactly what a translator exists to change. Tunnel mode does not help either, since AH then signs the immutable fields of the new outer header, which is the one the NAT rewrites. ## What the specifications concluded - **RFC 3715** (Informational, the IPsec-NAT compatibility requirements): NAT and AH are "fundamentally incompatible", and a compatibility solution need not support AH in either mode. - **RFC 3948** (UDP encapsulation of ESP): AH is left out of scope because protecting the outer addresses "is inherently incompatible with NAT". - **RFC 8221**: `ENCR_NULL` remains MUST so ESP can provide authentication only, "preferred over AH due to NAT traversal". - **RFC 4301**: implementations MUST support ESP and MAY support AH. ## What it means for an operator - If any device on the path translates addresses, AH cannot be used, in transport or tunnel mode. - Integrity without confidentiality is built as ESP with NULL encryption and an integrity algorithm. - AH remains workable only on paths you control end to end with no translation — and even there, ESP is the default the specifications point to.

  • Does AH also fail when a router remarks DSCP or decrements TTL on the way?
    No. RFC 4302 classifies DSCP, ECN, Flags, Fragment Offset, TTL and the IPv4 header checksum as mutable and zeroes them before computing and verifying the ICV, so ordinary forwarding and QoS remarking leave the check intact. Only fields classified as immutable — the addresses among them — break AH when they change in transit.
  • Would AH survive a NAT if both peers used tunnel mode instead of transport mode?
    No. In tunnel mode AH authenticates the immutable fields of the new outer IP header, except the mutable ones, just as it does for the original header in transport mode. The NAT rewrites that outer header's address, so the receiver's recomputed ICV still fails. Moving the original addresses inside does not help, because AH signs the outer ones too.
  • Why can't the NAT device simply recompute the AH ICV after translating?
    The ICV is keyed with the security association's secret, which only the two IPsec peers hold. A translator without it cannot produce a valid ICV; if any on-path device could re-sign packets after changing them, AH would no longer prove the packet came unaltered from the peer.

saying these in an interview costs you the question

  • NAT breaks AH because routers decrement the TTL that AH signs.
  • A NAT device could fix AH by recomputing the ICV after translating.
  • Wrapping AH in UDP lets it cross a NAT the same way ESP does.
  • Tunnel mode AH survives NAT because the original addresses move inside.
  • ESP's integrity check also covers the outer IP addresses.