TCP Encapsulation of IKE and IPsec Packets
obsoleted by
- rfc-9329 — TCP Encapsulation of Internet Key Exchange Protocol (IKE) and IPsec Packets
Extracted elements (31)
Running TCP within TCP is discouraged for performance reasons: outer TCP packet loss is hidden from inner TCP connections (interpreted as delay, not loss), causing spurious retransmissions, degraded RTT estimation, reduced sending rates, and potential bufferbloat.
TCP encapsulation is provided as a fallback option because many network middleboxes block all UDP traffic, including IKE and IPsec, but allow TCP connections through because they appear to be web traffic. Direct ESP or UDP encapsulation should be preferred due to performance concerns.
The 'IKETCP' stream prefix was chosen to identify and validate TCP connections used for TCP encapsulation and to avoid conflicts with the prevalence of previous non-standard protocols that also used TCP port 4500.
IKE_SA_INIT packets sent on a TCP connection SHOULD include NAT_DETECTION_SOURCE_IP and NAT_DETECTION_DESTINATION_IP payloads with the same content as when sending over UDP, using the applicable TCP ports when creating and checking the SHA-1 digests.
When a MOBIKE-enabled Initiator changes networks, UPDATE_SA_ADDRESSES SHOULD be sent over UDP first; if no UDP response, it is sent over TCP. The resulting encapsulation mode follows whichever transport received a response.
A peer MUST discard a partially received message due to a broken connection.
An implementation SHOULD NOT send IKE fragmentation fragments when going over a TCP connection, although it MUST support receiving fragments. If both MOBIKE and IKE fragmentation are supported, IKE fragmentation SHOULD be negotiated in case the session switches to UDP.
If TCP encapsulation is being used for a specific IKE SA, all messages for that IKE SA and its Child SAs MUST be sent over a TCP connection until the SA is deleted or MOBIKE is used to change the SA endpoints and/or encapsulation protocol.
If there is a syntax issue within an IKE message, an implementation MUST send the INVALID_SYNTAX notify payload and tear down the IKE SA as usual, rather than tearing down the TCP connection directly.
Implementations MUST support TCP encapsulation on TCP port 4500, which is reserved for IPsec NAT traversal.
Implementations SHOULD follow ECN compatibility mode for tunnel ingress as described in RFC 6040, marking the outer TCP connection as not ECN-capable and dropping inner packets if the outer header arrives marked with CE.
Implementations SHOULD prefer ESP direct or UDP-encapsulated SAs over TCP-encapsulated SAs when possible, due to performance trade-offs.
Implementations that implement both MOBIKE and TCP encapsulation MUST support dynamically enabling and disabling TCP encapsulation as interfaces change.
Individual packets on a TCP encapsulation connection SHOULD NOT use different QoS/DSCP markings than the rest of the connection, as different priorities may cause packets to be routed differently and introduce unnecessary delays.
IPsec ESP NAT keep-alives SHOULD NOT be sent when using TCP encapsulation, and any implementation using TCP encapsulation MUST silently drop incoming NAT keep-alive packets (one-octet 0xFF ESP payload) and not treat them as errors.
Multiple IKE SAs MUST NOT share a single TCP connection, unless one is a rekey of an existing IKE SA, in which case there will temporarily be two IKE SAs on the same TCP connection.
TCP keep-alives and TLS keep-alives MUST NOT be used as indications of IKE peer liveness; peer liveness should be checked using IKE informational packets.
The first bytes sent on a TCP stream MUST be the stream prefix 'IKETCP'. The TCP Responder MUST wait for the entire stream prefix to be received before trying to parse any IKE or ESP messages.
The Security Parameter Index (SPI) field in the TCP-encapsulated ESP header MUST NOT be a zero value, to ensure correct demultiplexing from IKE traffic.
The TCP Originator MUST remain the peer that originally initiated the first IKE SA even if the IKE SA is rekeyed one or more times.
The TCP Responder MUST allow packets for existing SAs to be received from new source ports, since new TCP connections may use different ports due to NAT mappings or local port allocation changes.
The TCP Responder MUST NOT accept any messages for an existing IKE session on a new incoming connection unless that connection begins with the stream prefix.
Whenever the TCP Originator opens a new TCP connection for an existing IKE SA, it MUST send the stream prefix first before any IKE or ESP messages.
Every TCP stream used for IKE and IPsec encapsulation MUST begin with a 6-byte magic stream prefix containing the ASCII characters 'IKETCP' (0x49 0x4b 0x45 0x54 0x43 0x50), sent once by the TCP Originator only.
This document updates the IANA port registry reference for TCP port 4500 (keyword: ipsec-nat-t) to RFC 8229, confirming its use for TCP-encapsulated IKE and ESP in addition to its existing IPsec NAT-Traversal role.
Attackers may disrupt TCP connections by sending spurious TCP Reset packets; implementations SHOULD ensure IKE session state persists even if the underlying TCP connection is torn down.
Because TCP encapsulation requires the TCP Responder to accept connections from new source addresses and ports, an attacker that can pass validation checks could redirect subsequent packets. Validation of messages on reconnection MUST include decryption, authentication, and replay checks.
IKE Responders supporting TCP encapsulation may become vulnerable to new DoS attacks specific to TCP, such as SYN-flooding attacks. TCP Responders should be aware of this additional attack surface.
Since TCP provides reliable, in-order delivery of ESP messages, the ESP anti-replay window size SHOULD be set to 1, increasing protection against replay attacks.
TCP-encapsulated ESP messages are preceded by a 16-bit unsigned integer Length field (network byte order) specifying the length of the ESP packet including the Length field itself, followed immediately by the ESP header.
TCP-encapsulated IKE messages are preceded by a 16-bit unsigned integer Length field (network byte order) giving the length of the IKE message including the non-ESP marker, followed by a 32-bit all-zeros Non-ESP Marker, then the IKE header.