RFC 9329

TCP Encapsulation of Internet Key Exchange Protocol (IKE) and IPsec Packets

๐Ÿ“… published November 2022, from ietf

(Part 1 of 8) ๐Ÿ’–

RFC 9329: TCP Encapsulation of IKE and IPsec Packets โœจ

Okay bestie, here's the tea ๐Ÿซถ This is an IETF Standards Track document (Category: Standards Track, ISSN 2070-1721), published in November 2022. The authors are T. Pauly from Apple Inc. and V. Smyslov from ELVIS-PLUS. It obsoletes RFC 8229 ๐Ÿฆ‹ and doesn't update anything else.


Abstract

Okay so this doc explains how to send IKE and IPsec packets over a TCP connection ๐ŸŒธ It's for getting past middleboxes that block IKE negotiation over UDP. The method is called "TCP encapsulation," and it sends both the IKE packets used to set up Security Associations (SAs) and the Encapsulating Security Payload (ESP) packets over one TCP connection. It's meant to be a fallback for when IKE can't be negotiated over UDP, so it's the backup plan, not the main plan ๐Ÿ’…

TCP encapsulation was first defined in RFC 8229. This document clarifies that spec with extra details that came up while people were implementing and deploying it ๐Ÿ“ It obsoletes RFC 8229.

Status of This Memo

This is an Internet Standards Track document โœจ

This document is a product of the Internet Engineering Task Force (IETF). It represents the consensus of the IETF community. It has received public review and has been approved for publication by the Internet Engineering Steering Group (IESG). Further information on Internet Standards is available in Section 2 of RFC 7841.

Info about the current status of this doc, any errata, and how to send feedback is at https://www.rfc-editor.org/info/rfc9329 ๐Ÿ”ฅ

Copyright (c) 2022 IETF Trust and the persons identified as the document authors. All rights reserved.

This document is subject to BCP 78 and the IETF Trust's Legal Provisions Relating to IETF Documents (https://trustee.ietf.org/license-info) in effect on the date of publication of this document. Please review these documents carefully, since they describe your rights and restrictions with respect to this document. Code Components extracted from this document must include Revised BSD License text as described in Section 4.e of the Trust Legal Provisions, and they are provided without warranty as described in the Revised BSD License. ๐Ÿ’œ

Table of Contents

1.  Introduction
  1.1.  Prior Work and Motivation
  1.2.  Terminology and Notation
2.  Configuration
3.  TCP-Encapsulated Data Formats
  3.1.  TCP-Encapsulated IKE Message Format
  3.2.  TCP-Encapsulated ESP Packet Format
4.  TCP-Encapsulated Stream Prefix
5.  Applicability
  5.1.  Recommended Fallback from UDP
6.  Using TCP Encapsulation
  6.1.  Connection Establishment and Teardown
  6.2.  Retransmissions
  6.3.  Cookies and Puzzles
    6.3.1.  Statelessness versus Delay of SA Establishment
  6.4.  Error Handling in IKE_SA_INIT
  6.5.  NAT-Detection Payloads
  6.6.  NAT-Keepalive Packets
  6.7.  Dead Peer Detection and Transport Keepalives
  6.8.  Implications of TCP Encapsulation on IPsec SA Processing
7.  Interaction with IKEv2 Extensions
  7.1.  MOBIKE Protocol
  7.2.  IKE Redirect
  7.3.  IKEv2 Session Resumption
  7.4.  IKEv2 Protocol Support for High Availability
  7.5.  IKEv2 Fragmentation
8.  Middlebox Considerations
9.  Performance Considerations
  9.1.  TCP-in-TCP
  9.2.  Added Reliability for Unreliable Protocols
  9.3.  Quality-of-Service Markings
  9.4.  Maximum Segment Size
  9.5.  Tunneling ECN in TCP
10. Security Considerations
11. IANA Considerations
12. References
  12.1.  Normative References
  12.2.  Informative References
Appendix A.  Using TCP Encapsulation with TLS
Appendix B.  Example Exchanges of TCP Encapsulation with TLS 1.3
  B.1.  Establishing an IKE Session
  B.2.  Deleting an IKE Session
  B.3.  Re-establishing an IKE Session
  B.4.  Using MOBIKE between UDP and TCP Encapsulation
Acknowledgments
Authors' Addresses

1. Introduction ๐ŸŽ€

So here's the setup. IKEv2 [RFC7296] is the protocol that sets up IPsec Security Associations (SAs). It sends IKE messages over UDP for control traffic, and it sends Encapsulating Security Payload (ESP) messages [RFC4303] for the encrypted data traffic. The problem is that lots of network middleboxes on public hotspots block all UDP traffic, IKE and IPsec included, but they let TCP connections through because those look like regular web traffic ๐Ÿ˜ญ So devices on those networks that need IPsec (to reach private enterprise networks, or to route Voice over IP calls to carrier networks because of security policies, and so on) just can't set up IPsec SAs. This document defines a way to wrap both IKE control messages and ESP data messages inside a TCP connection. Also, Authentication Header (AH) is not supported by this spec, so don't go looking for it here ๐Ÿ™ˆ

Using TCP as a transport for IPsec packets adds a third option to the usual IPsec transports:

  1. Direct. Usually, IKE negotiations start over UDP port 500. If no Network Address Translation (NAT) device is detected between the Initiator and the Responder, then the later IKE packets go over UDP port 500 and the IPsec data packets are sent using ESP.
  2. UDP Encapsulation. Described in [RFC3948]. If a NAT is detected between the Initiator and the Responder, then the later IKE packets go over UDP port 4500 with 4 bytes of zero at the start of the UDP payload, and the ESP packets are sent out over UDP port 4500. Some implementations default to UDP encapsulation even when no NAT is detected on the path, since some middleboxes don't support IP protocols other than TCP and UDP.
  3. TCP Encapsulation. Described in this document. If the other two methods aren't available or aren't a good fit, the IKE negotiation packets and the ESP packets can both be sent over a single TCP connection to the peer.

Direct use of ESP or UDP encapsulation should be preferred by IKE implementations, because TCP encapsulation has performance concerns (Section 9). Most implementations should only use TCP encapsulation on networks where negotiation over UDP has been tried without getting any responses from the peer, or on networks known not to support UDP ๐Ÿ’…

1.1. Prior Work and Motivation โœจ

Wrapping IKE connections inside TCP streams is a common way to fix the problem of UDP packets getting blocked by middleboxes. The specific goals of this document are:

  • Interoperability. To promote interoperability by defining a standard method of framing IKE and ESP messages within TCP streams.
  • Compatibility. To be compatible with the current IKEv2 standard without requiring modifications or extensions.
  • UDP first. To use IKE over UDP by default, avoiding the overhead of other alternatives that always rely on TCP or Transport Layer Security (TLS) [RFC5246] [RFC8446].

Some previous alternatives include:

  • Cellular Network Access. Interworking Wireless LAN (IWLAN) uses IKEv2 to create secure connections to cellular carrier networks, so people can make voice calls and access other network services over Wi-Fi networks. 3GPP has recommended that IKEv2 and ESP packets be sent within a TLS connection so they can establish connections on restrictive networks.
  • ISAKMP over TCP. Various non-standard extensions to the Internet Security Association and Key Management Protocol (ISAKMP) have been deployed that send IPsec traffic over TCP or TCP-like packets.
  • Secure Sockets Layer (SSL) VPNs. Many proprietary VPN solutions use a combination of TLS and IPsec to get reliability. These often run on TCP port 443.
  • IKEv2 over TCP. IKEv2 over TCP, as described in [IPSECME-IKE-TCP], is used to avoid UDP fragmentation.

TCP encapsulation for IKE and IPsec was defined in [RFC8229]. This document updates that spec by adding clarifications that came out of implementing and deploying the method ๐ŸŒˆ

Specifically:

  • The interpretation of the Length field preceding every message is clarified (Section 3).
  • The use of the NAT_DETECTION_*_IP notifications is clarified (Sections 5.1, 6.5, and 7.1).
  • Retransmission behavior is clarified (Section 6.2).
  • The use of cookies and puzzles is described in more detail (Section 6.3).
  • Error handling is clarified (Section 6.4).
  • Implications of TCP encapsulation on IPsec SA processing are expanded (Section 6.8).
  • Section 7, describing interactions with other IKEv2 extensions, is added.
  • The interaction of TCP encapsulation with IKEv2 Mobility and Multihoming (MOBIKE) is clarified (Section 7.1).
  • The recommendation for TLS encapsulation (Appendix A) now includes TLS 1.3.
  • Examples of TLS encapsulation are provided using TLS 1.3 (Appendix B).
  • More security considerations are added.

1.2. Terminology and Notation ๐Ÿงš

This document separates two things: the IKE peer that starts the TCP connections used for TCP encapsulation, and the roles of Initiator and Responder for particular IKE messages. During IKE exchanges, the IKE Initiator and Responder roles can swap for a given SA (like with IKE SA rekeys), but the one who started the TCP connection is still responsible for tearing it down and setting it up again if needed. So this document uses the term "TCP Originator" for the IKE peer that initiates TCP connections, and "TCP Responder" for the peer that receives them. If an IKE SA is rekeyed one or more times, the TCP Originator MUST remain the peer that originally initiated the first IKE SA ๐Ÿซถ

The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in BCP 14 [RFC2119] [RFC8174] when, and only when, they appear in all capitals, as shown here.


2. Configuration ๐Ÿ’–

One of the main reasons to use TCP encapsulation is that UDP traffic may be entirely blocked on a network. Because of that, support for TCP encapsulation isn't negotiated in the IKE exchange. Instead, support for TCP encapsulation must be preconfigured on both the TCP Originator and the TCP Responder ๐ŸŒธ

Compliant implementations MUST support TCP encapsulation on TCP port 4500, which is reserved for IPsec NAT traversal.

Beyond a flag indicating support for TCP encapsulation, the configuration for each peer can include the following optional parameters:

  • Alternate TCP ports. The specific TCP ports the TCP Responder listens on for incoming connections. Note that the TCP Originator may initiate TCP connections to the TCP Responder from any local port.
  • An extra framing protocol. An additional framing protocol to use on top of TCP to further encapsulate the stream of IKE and IPsec packets. See Appendix A for a detailed discussion.

Since TCP encapsulation of IKE and IPsec packets adds overhead and has potential performance trade-offs compared to direct or UDP-encapsulated SAs (as described in Section 9), implementations SHOULD prefer ESP direct or UDP-encapsulated SAs over TCP-encapsulated SAs when possible. โœจ

3. TCP-Encapsulated Data Formats โœจ

Okay so, just like UDP encapsulation, TCP encapsulation checks the first 4 bytes of a message to tell IKE and ESP messages apart ๐Ÿฆ‹. It also adds a 16-bit Length field before every message so the receiver knows where each message ends in the stream ๐Ÿ’…. That Length value is the length of the original message plus the length of the field itself, in octets. If the first 32 bits are zeros (that's the non-ESP marker), the contents are an IKE message. Otherwise, it's an ESP message. AH messages are not supported for TCP encapsulation, sorry AH ๐Ÿ™ˆ

Ngl, a TCP stream can technically send super long messages, but implementations SHOULD limit message lengths to match the lengths used for UDP encapsulation of ESP messages ๐ŸŒธ Why? The maximum message length becomes the effective MTU for connections being encrypted with ESP, so it changes things like the TCP Maximum Segment Size (MSS) ๐Ÿ‘‘

Since the Length field is 16 bits and counts both the message and the field itself, it is impossible to encapsulate messages greater than 65533 octets in length. In most cases that's not a problem ๐Ÿซถ Note that a similar limitation exists for encapsulation ESP in UDP [RFC3948].

The minimum size of an encapsulated message is 1 octet (for NAT-keepalive packets, see Section 6.6). Empty messages (where the Length field equals 2) MUST be silently ignored by receiver.

Note that this method of encapsulation will also work for placing IKE and ESP messages within any protocol that presents a stream abstraction, beyond TCP. ๐Ÿงš

3.1. TCP-Encapsulated IKE Message Format

                        1                   2                   3
    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
                                   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
                                   |            Length             |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                         Non-ESP Marker                        |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                                                               |
   ~                     IKE Message (RFC 7296)                    ~
   |                                                               |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

Figure 1: IKE Message Format for TCP Encapsulation

The IKE message is preceded by a 16-bit Length field in network byte order that specifies the length of the IKE message (including the non-ESP marker) within the TCP stream. Just like IKE over UDP port 4500, a zeroed 32-bit non-ESP marker is inserted before the start of the IKE header, so the traffic can be told apart from ESP traffic between the same addresses and ports ๐ŸŽ€

  • Length (2 octets, unsigned integer): Length of the IKE message, including the Length field and non-ESP marker. The value in the Length field MUST NOT be 0 or 1. The receiver MUST treat these values as fatal errors and MUST close the TCP connection. ๐Ÿ’€
  • Non-ESP Marker (4 octets): Four zero-valued bytes.

3.2. TCP-Encapsulated ESP Packet Format

                        1                   2                   3
    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
                                   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
                                   |            Length             |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                                                               |
   ~                     ESP Packet (RFC 4303)                     ~
   |                                                               |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

Figure 2: ESP Packet Format for TCP Encapsulation

The ESP packet is preceded by a 16-bit Length field in network byte order that specifies the length of the ESP packet within the TCP stream.

The Security Parameter Index (SPI) field [RFC7296] in the ESP header MUST NOT be a zero value. ๐Ÿ”ฅ

  • Length (2 octets, unsigned integer): Length of the ESP packet, including the Length field. The value in the Length field MUST NOT be 0 or 1. The receiver MUST treat these values as fatal errors and MUST close TCP connection. ๐Ÿ˜ญ

4. TCP-Encapsulated Stream Prefix

Each stream of bytes used for IKE and IPsec encapsulation MUST begin with a fixed sequence of 6 bytes as a magic value, containing the characters "IKETCP" as ASCII values. ๐ŸŒˆ

      0      1      2      3      4      5
   +------+------+------+------+------+------+
   | 0x49 | 0x4b | 0x45 | 0x54 | 0x43 | 0x50 |
   +------+------+------+------+------+------+

Figure 3: TCP-Encapsulated Stream Prefix

This value is there to identify and validate that the TCP connection is being used for TCP encapsulation as defined in this document. That way it avoids conflicts with the many non-standard protocols that already used TCP port 4500 ๐Ÿ™ˆ This value is only sent once, by the TCP Originator only, at the beginning of the TCP stream of IKE and ESP messages.

   Initiator                                                   Responder
   ---------------------------------------------------------------------
             <new TCP connection is established by Initiator>

   Stream Prefix|Length|non-ESP marker|IKE message -->
                                   <-- Length|non-ESP marker|IKE message
   Length|non-ESP marker|IKE message -->
                                   <-- Length|non-ESP marker|IKE message

                                   [...]
   Length|ESP packet ->
                                                    <- Length|ESP packet

If other framing protocols are used within TCP to further encapsulate or encrypt the stream of IKE and ESP messages, the stream prefix must be at the start of the TCP Originator's IKE and ESP message stream within the added protocol layer (Appendix A). Although some framing protocols do support negotiating inner protocols, the stream prefix should always be used so implementations stay as generic as possible and don't rely on other framing protocols on top of TCP ๐Ÿงš

5. Applicability

TCP encapsulation is applicable only when it has been configured to be used with specific IKE peers. If a Responder is configured to accept and is allowed to use TCP encapsulation, it MUST listen on the configured port(s) in case any peers will initiate new IKE sessions. Initiators MAY use TCP encapsulation for any IKE session to a peer that is configured to support TCP encapsulation, although it is recommended that Initiators only use TCP encapsulation when traffic over UDP is blocked. ๐Ÿฆ‹

Since the support of TCP encapsulation is a configured property, not a negotiated one, it is recommended that if there are multiple IKE endpoints representing a single peer (such as multiple machines with different IP addresses when connecting by Fully Qualified Domain Name (FQDN), or endpoints used with IKE redirection), all of the endpoints equally support TCP encapsulation. ๐Ÿ‘‘

If TCP encapsulation is being used for a specific IKE SA, all IKE messages for that IKE SA and ESP packets for its Child SAs MUST be sent over a TCP connection until the SA is deleted or IKEv2 Mobility and Multihoming (MOBIKE) is used to change the SA endpoints and/or the encapsulation protocol. See Section 7.1 for more details on using MOBIKE to transition between encapsulation modes. ๐Ÿ’…

Since UDP is the preferred method of transport for IKE messages, implementations that use TCP encapsulation should have an algorithm for deciding when to use TCP after determining that UDP is unusable. If an Initiator implementation has no prior knowledge about the network it is on and the status of UDP on that network, it SHOULD always attempt to negotiate IKE over UDP first. IKEv2 defines how to use retransmission timers with IKE messages and, specifically, IKE_SA_INIT messages [RFC7296]. Generally, this means that the implementation will define a frequency of retransmission and the maximum number of retransmissions allowed before marking the IKE SA as failed. An implementation can attempt negotiation over TCP once it has hit the maximum retransmissions over UDP, or slightly before, to reduce connection setup delays. It is recommended that the initial message over UDP be retransmitted at least once before falling back to TCP, unless the Initiator knows beforehand that the network is likely to block UDP. โญ

When switching from UDP to TCP, a new IKE_SA_INIT exchange MUST be initiated with the Initiator's new SPI and with recalculated content of NAT_DETECTION_*_IP notifications. ๐Ÿซถ

6. Using TCP Encapsulation โœจ

6.1. Connection Establishment and Teardown โœจ

okay so when the IKE Initiator uses TCP encapsulation, it opens a TCP connection to the Responder on the Responder's preconfigured TCP port ๐Ÿ”Œ The very first bytes on that TCP stream MUST be the stream prefix value (Section 4) ๐ŸŽ€ After the prefix, encapsulated IKE messages negotiate the IKE SA and initial Child SA [RFC7296] ๐Ÿ’… Then both encapsulated IKE (Figure 1) and ESP (Figure 2) messages ride the TCP connection together ๐Ÿฆ‹ The TCP Responder MUST wait for the entire stream prefix to arrive before it tries to parse any IKE or ESP messages ๐Ÿ™ˆ The stream prefix only gets sent once, and only the TCP Originator sends it ๐ŸŒธ

To close an IKE session, either the Initiator or Responder SHOULD gracefully tear down the IKE SAs using DELETE payloads ๐Ÿงน Once the SA is deleted, the TCP Originator SHOULD close the TCP connection, as long as it doesn't plan on using that connection for another IKE session to the TCP Responder ๐Ÿซถ If the TCP connection isn't tied to any active IKE SA anymore, the TCP Responder MAY close it to clean up IKE resources, but only if the TCP Originator hasn't closed it within some reasonable period of time (e.g., a few seconds) โฑ๏ธ

An unexpected FIN or a TCP Reset on the connection might mean loss of connectivity, an attack, or some other error ๐Ÿ˜ญ If no DELETE payload has been sent, both sides SHOULD keep the state for their SAs for the standard lifetime or timeout period ๐Ÿง  The TCP Originator is responsible for re-establishing the TCP connection if it gets torn down for any unexpected reason ๐Ÿ” New TCP connections can use different IP addresses and/or ports because of NAT mappings or changes to local address or port allocations, so the TCP Responder MUST allow packets for existing SAs to be received from new source IP addresses and ports ๐ŸŒˆ Also, the IPv6 Flow-ID header MUST remain constant when a new TCP connection is created, so that ECMP load balancing doesn't split things up ๐Ÿงฉ

A peer MUST discard a partially received message when the connection breaks ๐Ÿ—‘๏ธ

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 ๐Ÿ’– This is the same behavior as the initial TCP connection, so nothing new to learn here ๐Ÿ˜Œ

Multiple IKE SAs MUST NOT share a single TCP connection, unless one of them is a rekey of an existing IKE SA. In that case, there will temporarily be two IKE SAs on the same TCP connection ๐Ÿ”€

If a TCP connection is being used to continue an existing IKE/ESP session, the TCP Responder can recognize the session using either the IKE SPI from an encapsulated IKE message or the ESP SPI from an encapsulated ESP packet ๐Ÿ” If the session was fully established before, it is suggested that the TCP Originator send an UPDATE_SA_ADDRESSES message if MOBIKE is supported, and an empty informational message if it isn't ๐Ÿ“ฌ

The TCP Responder MUST NOT accept any messages for the existing IKE session on a new incoming connection, unless that connection begins with the stream prefix ๐Ÿšซ If either the TCP Originator or TCP Responder detects corruption on a connection that was started with a valid stream prefix, it SHOULD close the TCP connection ๐Ÿ’€ The connection can be corrupted if there are too many subsequent messages that can't be parsed as valid IKE messages or as ESP messages with known SPIs, or if the authentication check for an IKE message or ESP message with a known SPI fails ๐Ÿ™…โ€โ™€๏ธ Implementations SHOULD NOT tear down a connection just because a few consecutive ESP packets have unknown SPIs, since the SPI databases may be momentarily out of sync ๐Ÿ•ฐ๏ธ If the problem is a syntax issue within an IKE message instead, 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 ๐Ÿ“

A TCP Originator SHOULD only open one TCP connection per IKE SA, and send all of the corresponding IKE and ESP messages over it ๐ŸŽฏ This helps make sure that any firewall or NAT mappings allocated for the TCP connection apply equally to all of the traffic for that IKE SA ๐Ÿ›ก๏ธ

Just like TCP Originators, a TCP Responder SHOULD send packets for an IKE SA and its Child SAs over only one TCP connection at any given time ๐Ÿ‘‘ It SHOULD choose the TCP connection on which it last received a valid and decryptable IKE or ESP message. To count as valid for choosing a TCP connection, an IKE message has to be successfully decrypted and authenticated, not be a retransmission of a previously received message, and fall within the expected window for IKE message IDs โœ… An ESP message has to be successfully decrypted and authenticated, and must not be a replay of a previous message (okay, I'm obsessed with how strict this is ๐Ÿค“)

Since a connection can break and get re-established by the TCP Originator without the TCP Responder knowing, a TCP Responder SHOULD accept IKE and ESP messages on both old and new connections until the old connection is closed by the TCP Originator ๐Ÿงƒ A TCP Responder MAY close a TCP connection it sees as idle and extraneous (one that was previously used for IKE and ESP messages but has been replaced by a new connection) ๐Ÿงน


6.2. Retransmissions ๐Ÿ”„

Section 2.1 of [RFC7296] explains how IKEv2 deals with the unreliability of UDP ๐Ÿซ  Quick recap: the exchange Initiator handles retransmissions and has to keep retransmitting request messages until it gets a response message. If no reply comes back after several retransmissions, the SA gets deleted ๐Ÿ’” The Responder never starts a retransmission itself, but it has to send a response message again if it receives a retransmitted request ๐Ÿ”

When IKEv2 uses a reliable transport protocol like TCP, the retransmission rules look like this ๐Ÿง

  • The exchange Initiator SHOULD NOT retransmit request message ((*)); if no response is received within some reasonable period of time, the IKE SA is deleted.
  • If a new TCP connection for the IKE SA is established while the exchange Initiator is waiting for a response, the Initiator MUST retransmit its request over this new connection and keep waiting for a response ๐Ÿช„
  • The exchange Responder doesn't change its behavior, and acts as described in Section 2.1 of [RFC7296] ๐Ÿ™Œ

(*) This is an optimization. Implementations may keep using the retransmission logic from Section 2.1 of [RFC7296] if they want to keep things simple ๐Ÿงธ


6.3. Cookies and Puzzles ๐Ÿช

IKEv2 has a DoS attack protection mechanism called Cookies, described in Section 2.6 of [RFC7296] ๐Ÿ›ก๏ธ [RFC8019] extends this for protection against DDoS attacks with Client Puzzles ๐Ÿงฉ Both mechanisms let the Responder avoid keeping state until the Initiator proves its IP address is legit (and, if required, after solving a puzzle) ๐Ÿ•ต๏ธโ€โ™€๏ธ

Connection-oriented TCP transport adds some extra things to think about when using these mechanisms ๐Ÿค” In general, Cookies give less value with TCP encapsulation. By the time a Responder gets the IKE_SA_INIT request, the TCP session is already established and the Initiator's IP address has already been verified ๐Ÿ˜… Also, a TCP/IP stack creates state as soon as it receives a TCP SYN packet (unless SYN Cookies from [RFC4987] are used), which clashes with the statelessness of IKEv2 Cookies ๐Ÿ’… With TCP, an attacker can mount a SYN flooding DoS attack that an IKEv2 Responder can't stop with stateless IKEv2 Cookies ๐Ÿ˜ฑ So with TCP encapsulation, sending Cookie requests without Puzzles makes little sense, unless the Responder is worried about TCP sequence number attacks (see [RFC6528] and [RFC9293] for details). Puzzles still stay useful, though, and using them requires using Cookies too ๐Ÿง

These are the things to keep in mind when using the Cookie and Puzzle mechanisms with TCP encapsulation ๐Ÿ“‹

  • The exchange Responder SHOULD NOT send an IKEv2 Cookie request without an accompanying Puzzle. Implementations might make exceptions for cases like mitigating TCP sequence number attacks ๐Ÿ™
  • If the Responder chooses to send a Cookie request (possibly along with a Puzzle request), then the TCP connection the IKE_SA_INIT request arrived over SHOULD be closed after the Responder sends its reply, provided no repeated requests show up within some short period of time. This keeps the Responder stateless (see Section 6.3.1) ๐Ÿซง The Responder MUST NOT include the Initiator's TCP port in the Cookie calculation ((*)), because the Cookie can come back over a new TCP connection with a different port ๐Ÿšท
  • The exchange Initiator acts as described in Section 2.6 of [RFC7296] and Section 7 of [RFC8019], so using TCP encapsulation doesn't change the Initiator's behavior ๐Ÿ™†โ€โ™€๏ธ

(*) The examples of Cookie calculation methods in Section 2.6 of [RFC7296] and Section 7.1.1.3 of [RFC8019] don't include transport protocol ports. These examples are only for illustration, though, since the Cookie generation algorithm is a local matter. Some implementations might include port numbers that won't work with TCP encapsulation ๐Ÿง  Those examples also include the Initiator's IP address in the Cookie calculation. That address can change between two initial requests (one with a Cookie and one without), because NATs have more freedom to change source IP addresses for new TCP connections than for UDP ๐ŸŒฌ๏ธ In those cases, cookie verification might fail ๐Ÿ˜ฌ

6.3.1. Statelessness versus Delay of SA Establishment โณ

There's a trade-off in picking how long to wait before closing the TCP connection โš–๏ธ If the time is too short, the proper Initiator that repeats its request will need to re-establish the TCP connection, which adds delay ๐Ÿข If it's too long, the Responder's resources get wasted when the Initiator never comes back ๐Ÿชฆ This document doesn't mandate a duration because it doesn't affect interoperability, but it is believed that 5-10 seconds is a good compromise ๐ŸŽฏ Also, if the Responder asks the Initiator to solve a puzzle, the Responder can estimate how long that would take the Initiator and adjust the time interval to match โœจ

6.4. Error Handling in IKE_SA_INIT ๐Ÿ’Œ

Okay bestie, so Section 2.21.1 of [RFC7296] explains how error notifications get handled in the IKE_SA_INIT exchange. The advice is that the Initiator should not act right away after getting an error notification. It should wait a bit for a valid response, because IKE_SA_INIT messages are totally unauthenticated ๐Ÿ™ˆ. But ngl, this advice doesn't hit the same way with TCP encapsulation. If the Initiator gets a response over TCP, then either it's genuine and the peer really sent it, or the TCP session got hijacked and the message is forged. And if it got hijacked, no genuine messages from the Responder are gonna show up at all ๐Ÿ’€.

So with TCP encapsulation, an Initiator SHOULD NOT wait for additional messages if it gets an error notification from the Responder in the IKE_SA_INIT exchange. ๐Ÿซถ

Now, in the IKE_SA_INIT exchange, if the Responder returns an error notification that implies a recovery action from the Initiator (like INVALID_KE_PAYLOAD or INVALID_MAJOR_VERSION, see Section 2.21.1 of [RFC7296]), the Responder SHOULD NOT close the TCP connection immediately. The Responder is basically expecting the Initiator to repeat the request with corrected parameters, so it should hang tight. See also Section 6.3. ๐ŸŽ€


6.5. NAT-Detection Payloads ๐ŸŒธ

When negotiating over UDP, IKE_SA_INIT packets include NAT_DETECTION_SOURCE_IP and NAT_DETECTION_DESTINATION_IP payloads to figure out whether UDP encapsulation of IPsec packets should be used. These payloads contain SHA-1 digests of the SPIs, IP addresses, and ports, as defined in [RFC7296].

IKE_SA_INIT packets sent on a TCP connection SHOULD include these payloads with the same content as when sending over UDP, and they SHOULD use the applicable TCP ports when creating and checking the SHA-1 digests. Main character energy, the ports just switch to TCP. โœจ

If a NAT is detected because the SHA-1 digests don't match the expected values, no change should be made for encapsulation of subsequent IKE or ESP packets. The reason is that TCP encapsulation inherently supports NAT traversal, so it's already sorted ๐Ÿ’…. However, for the transport mode IPsec SAs, implementations need to handle TCP and UDP packet checksum fixup during decapsulation, as defined for UDP encapsulation in [RFC3948]. That part is a little extra, so don't skip it ๐Ÿ‘€.

Implementations MAY use the information that a NAT is present to influence keepalive timer values. ๐Ÿงš


6.6. NAT-Keepalive Packets ๐Ÿฆ‹

Encapsulating IKE and IPsec inside of a TCP connection can change the strategy that implementations use to maintain middlebox port mappings. Lowkey a big deal.

In general, TCP port mappings are maintained by NATs for longer than UDP port mappings. Because of that, IPsec ESP NAT-keepalive packets [RFC3948] SHOULD NOT be sent when using TCP encapsulation. ๐Ÿ™…โ€โ™€๏ธ Any implementation using TCP encapsulation MUST silently drop incoming NAT-keepalive packets and must not treat them as errors. Don't be dramatic about it, just drop them quietly ๐Ÿคซ.

NAT-keepalive packets over a TCP-encapsulated IPsec connection will be sent as a 1-octet-long payload with the value 0xFF, preceded by the 2-octet Length. That Length is set to 3, since it includes the length of the Length field itself. Math checks out, periodt ๐Ÿงฎ๐Ÿ’–.


6.7. Dead Peer Detection and Transport Keepalives โœจ

Peer liveness should be checked using IKE informational packets [RFC7296]. That's the main move ๐Ÿ‘‘.

Depending on how TCP and TLS are configured on the connection, TCP keep-alives [RFC1122] and TLS keep-alives [RFC6520] MAY be used. Here's the tea though: these MUST NOT be used as indications of IKE peer liveness. For that job, the standard IKEv2 mechanism is used instead, which is exchanging (usually empty) INFORMATIONAL messages (see Section 1.4 of [RFC7296]). Don't mix up the vibes, bestie ๐Ÿ™ˆ.


6.8. Implications of TCP Encapsulation on IPsec SA Processing ๐ŸŒˆ

Using TCP encapsulation affects some aspects of IPsec SA processing. Let's look at the big ones ๐Ÿ‘€.

  1. Section 8.1 of [RFC4301] requires all tunnel mode IPsec SAs to be able to copy the Don't Fragment (DF) bit from the inner IPv4 header to the outer (tunnel) one. With TCP encapsulation, this is generally not possible. The reason is that the TCP/IP stack manages the DF bit in the outer IPv4 header, and the stack usually makes sure the DF bit is set for TCP packets to avoid IP fragmentation. Note that this behavior is compliant with generic tunneling considerations, since the outer TCP header acts as a link-layer protocol, and its fragmentation and reassembly have no correlation with the inner payload. It's giving layered and intentional ๐Ÿง….
  2. The other feature that's less applicable with TCP encapsulation is the ability to split traffic of different QoS classes into different IPsec SAs, which are created by a single IKE SA. Normally, the Differentiated Services Code Point (DSCP) field is copied from the inner IP header to the outer (tunnel) one, so IPsec traffic of each SA gets the matching level of service. With TCP encapsulation, though, all IPsec SAs created by a single IKE SA share a single TCP connection. So they all receive the same level of service (see Section 9.3). If this functionality is needed, implementations should create several IKE SAs, each over separate TCP connections, and assign a corresponding DSCP value to each of them. Little bit of extra setup, but iconic ๐ŸŽ€.

TCP encapsulation of IPsec packets may have implications on the performance of the encapsulated traffic. Performance considerations are discussed in Section 9. ๐Ÿš€


7. Interaction with IKEv2 Extensions โœจ


7.1. MOBIKE Protocol ๐Ÿฆ‹

The MOBIKE protocol, which lets SAs migrate between IP addresses, is defined in [RFC4555]. [RFC4621] further clarifies the details of the protocol. When an IKE session that has negotiated MOBIKE is moving between networks, the Initiator of the transition may switch between using TCP encapsulation, UDP encapsulation, or no encapsulation. Implementations that implement both MOBIKE and TCP encapsulation within the same connection configuration MUST support dynamically enabling and disabling TCP encapsulation as interfaces change. That's a whole shapeshifter situation ๐ŸฆŽ.

When a MOBIKE-enabled Initiator changes networks, the INFORMATIONAL exchange with the UPDATE_SA_ADDRESSES notification SHOULD be initiated over UDP first, before attempting over TCP. If there is a response to the request sent over UDP, then the ESP packets should be sent directly over IP or over UDP port 4500 (depending on whether a NAT was detected). This happens regardless of whether a connection on a previous network was using TCP encapsulation. If no response is received within a certain period of time after several retransmissions, the Initiator ought to change its transport for this exchange from UDP to TCP and resend the request message. A new INFORMATIONAL exchange MUST NOT be started in this situation. If the Responder only responds to the request sent over TCP, then the ESP packets should be sent over the TCP connection, regardless of whether a connection on a previous network did not use TCP encapsulation. ๐ŸŒธ

The value of the timeout and the specific number of retransmissions before switching to TCP can vary depending on the Initiator's configuration. Implementations ought to provide reasonable defaults so that UDP attempts have a chance to succeed, but they can shorten the timeout based on historical data or metrics. โฑ๏ธ

If the TCP transport was used for the previous network connection, the old TCP connection SHOULD be closed by the Initiator once MOBIKE finishes migrating to a new connection (either TCP or UDP). Clean up after yourself, bestie ๐Ÿงน.

Since switching from UDP to TCP can happen during a single INFORMATIONAL message exchange, the content of the NAT_DETECTION_*_IP notifications will in most cases be incorrect (since the UDP and TCP ports will most likely be different). That means the peer may incorrectly detect the presence of a NAT. ๐Ÿ˜ญ Section 3.5 of [RFC4555] states that a new INFORMATIONAL exchange with the UPDATE_SA_ADDRESSES notify is initiated in case the address (or transport) is changed while waiting for a response.

Section 3.5 of [RFC4555] also states that once an IKE SA is switched to a new IP address, all outstanding requests in this SA are immediately retransmitted using this address. See also Section 6.2. ๐Ÿ”

The MOBIKE protocol defines the NO_NATS_ALLOWED notification, which can be used to detect the presence of a NAT between peers and to refuse to communicate in that situation. In the case of TCP, the NO_NATS_ALLOWED notification SHOULD be ignored, because TCP generally has no problems with NAT boxes. Ignore that one, it's not the vibe for TCP ๐Ÿ™„.

Section 3.7 of [RFC4555] describes an additional optional step in the process of changing IP addresses, called "Return Routability Check". It is performed by Responders to be sure that the new Initiator's address is actually routable. In the case of TCP encapsulation, this check has little value, since a TCP handshake already proves the routability of the TCP Originator's address. So the Return Routability Check SHOULD NOT be performed. ๐Ÿ™…โ€โ™€๏ธ


7.2. IKE Redirect ๐Ÿงš

A redirect mechanism for IKEv2 is defined in [RFC5685]. This mechanism lets security gateways redirect clients to another gateway, either during IKE SA establishment or after session setup. If a client is connecting to a security gateway using TCP and then gets redirected to another security gateway, the client needs to reset its transport selection. In other words, with the next security gateway, the client MUST first try UDP and then fall back to TCP while establishing a new IKE SA. This applies regardless of the transport of the SA the redirect notification was received over, unless the client's configuration tells it to instantly use TCP for the gateway it's redirected to. Fresh start, new gateway, new rules ๐Ÿ’….


7.3. IKEv2 Session Resumption ๐Ÿ’œ

Session resumption for IKEv2 is defined in [RFC5723]. Once an IKE SA is established, the server creates a resumption ticket where information about this SA is stored, and transfers this ticket to the client. The ticket may be used later to resume the IKE SA after it is deleted. When resumption happens, the client presents the ticket in a new exchange called IKE_SESSION_RESUME. Some parameters in the new SA are retrieved from the ticket, and others are renegotiated (more details are given in Section 5 of [RFC5723]).

Since network conditions may change while the client is inactive, the fact that TCP encapsulation was used in an old SA SHOULD NOT affect which transport is used during session resumption. In other words, the transport should be selected as if the IKE SA is being created from scratch. Clean slate, no baggage ๐ŸŒˆโœจ.

7.4. IKEv2 Protocol Support for High Availability โœจ

okay so [RFC6311] is the one that defines High Availability support in IKEv2 ๐Ÿ’–. When a cluster fails over, the new active node has to immediately start a special INFORMATION exchange containing the IKEV2_MESSAGE_ID_SYNC notification ๐Ÿฆ‹. That notification tells the client to skip some number of Message IDs, because they might not be synced between the nodes yet at the moment of failover.

Syncing states over TCP encapsulation is way harder than over UDP ๐Ÿ˜ญ. You need access to the TCP/IP stack internals, and an IKE/IPsec implementation doesn't always have that access. So if a cluster doesn't sync TCP states between nodes, the new active node won't have any TCP connection with the client after failover. It can't start the INFORMATIONAL exchange like [RFC6311] requires. The cluster usually acts as the TCP Responder, and only the TCP Originator can re-establish a TCP connection, so the new node can't do that either ๐Ÿ’€.

Now the client's side of things is a little sad. The failover might go totally unnoticed for a long time if the client has no IKE or ESP traffic to send ๐Ÿ™ˆ. The moment the client sends an ESP or IKEv2 packet, the cluster node answers with a TCP RST. Then the client, as the TCP Originator, re-establishes the TCP connection, and the node can finally start the INFORMATIONAL exchange to tell the client about the failover ๐Ÿซถ.

So this document makes the following recommendation ๐ŸŒธ: if High Availability support in IKEv2 is negotiated and TCP transport is used, a client that is a TCP Originator SHOULD periodically send IKEv2 messages (e.g., by initiating a liveness check exchange) whenever there is no IKEv2 or ESP traffic. This is different from what Section 2.4 of [RFC7296] recommends, because the liveness check should happen periodically even if the client has nothing to send over ESP. The sending frequency should be high enough to allow quick detection and restoration of broken TCP connections ๐Ÿ”ฅ.


7.5. IKEv2 Fragmentation

IKE message fragmentation [RFC7383] is not required when you're using TCP encapsulation ๐Ÿ’…, since a TCP stream already handles splitting its contents across packets. Fragmentation is redundant in this case, so implementations might choose to not negotiate IKE fragmentation ๐Ÿงš. Even if fragmentation is negotiated, an implementation SHOULD NOT send fragments when going over a TCP connection. It MUST still support receiving fragments though ๐ŸŽ€.

If an implementation supports both MOBIKE and IKE fragmentation, it SHOULD negotiate IKE fragmentation over a TCP-encapsulated session. That way, if the session switches to UDP encapsulation on another network, it's already covered โœจ๐Ÿฆ‹.


8. Middlebox Considerations ๐Ÿงฑ

Lots of security networking devices keep the state of sessions that go through them ๐Ÿ‘€. That includes firewalls, intrusion prevention systems, network optimization/acceleration devices, and NAT devices.

These devices often track transport-layer and/or application-layer data so they can drop traffic that looks anomalous or malicious ๐Ÿ•ต๏ธโ€โ™€๏ธ. Many of them are more likely to pass TCP-encapsulated traffic than UDP-encapsulated traffic, but some may still block or interfere with TCP-encapsulated IKE and IPsec traffic ๐Ÿ˜ค.

A network device that monitors the transport layer will track the state of TCP sessions, like TCP sequence numbers. If the IKE implementation has its own minimal TCP implementation, it SHOULD still use common TCP behaviors so it doesn't get dropped by middleboxes ๐Ÿ’œ.

Operators that intentionally block IPsec because of security implications might also want to block TCP port 4500, or use other methods to reject TCP-encapsulated IPsec traffic (e.g., filter out TCP connections that begin with the IKETCP stream prefix). Main character energy for security teams ๐Ÿ’€๐Ÿ”’.

9. Performance Considerations ๐ŸŽ๏ธ

Several aspects of TCP encapsulation for IKE and IPsec packets can hurt performance for connections inside a tunnel-mode IPsec SA ๐Ÿ˜ฉ. Implementations should be aware of these performance impacts and take them into account when deciding when to use TCP encapsulation. Implementations MUST favor direct ESP or UDP encapsulation over TCP encapsulation whenever possible ๐Ÿ‘‘.


9.1. TCP-in-TCP

If the outer connection between IKE peers is over TCP, the inner TCP connections can suffer from using TCP within TCP ๐ŸŒ€. Running TCP within TCP is discouraged, because TCP algorithms generally assume they're running over an unreliable datagram layer. Not ideal bestie ๐Ÿ˜ญ.

If the outer (tunnel) TCP connection loses packets, the inner TCP connections don't see the loss at all, since the outer connection retransmits to cover it ๐Ÿ™ˆ. But the outer connection delivers inner messages in order, so anything after a lost packet may have to wait until the loss is recovered. This means loss on the outer connection only looks like delay to inner connections โณ. Inner traffic can get burstier too, since a bunch of inner packets might get delivered across the tunnel all at once ๐Ÿ’ฅ. The inner TCP connection might read a long delay as a transmission problem and trigger a retransmission timeout, which causes spurious retransmissions. If those retransmissions aren't detected as spurious in time, the inner connection's sending rate may get reduced for no reason ๐Ÿ˜ค.

The inner connection's round-trip-time estimation is also affected by the burstiness of the outer TCP connection. If packets get retransmitted by the outer TCP connection after long delays, the inner connection's congestion control loop becomes less reactive. That can permanently keep its sending rate lower than the outer TCP would allow ๐Ÿข.

TCP-in-TCP can also cause "TCP meltdown" ๐Ÿซ , where stacked TCP instances seriously hurt performance [TCP-MELTDOWN]. It happens when losses in the lower TCP (closer to the link) increase the delays the higher TCP (closer to the application) sees. Those delays create timeouts, which cause retransmissions, which can then cause losses in the lower TCP by overrunning its buffer. The very mechanism meant to avoid loss (retransmission) ends up working across both layers to increase loss ๐Ÿ’€. To limit this, the timeouts of the two TCP layers need to be carefully managed, e.g., so the higher layer has a much longer timeout than the lower layer ๐Ÿง .

Any negative effects get shared by all flows going through the outer TCP connection ๐Ÿฅบ. That's a big deal for latency-sensitive or real-time apps using the tunnel. If that traffic is running over a TCP-encapsulated IPsec connection, it is recommended that the number of inner connections sharing the tunnel be limited as much as possible ๐Ÿ“‰๐Ÿซถ.


9.2. Added Reliability for Unreliable Protocols

ESP is an unreliable protocol, so sending ESP packets over a TCP connection changes how those packets fundamentally behave ๐Ÿ”„. Some application-level protocols prefer packet loss to delay, like Voice over IP or other real-time protocols ๐Ÿ“ž. Those can get messed up if the TCP connection retransmits their packets after a loss ๐Ÿ˜ฉ.


9.3. Quality-of-Service Markings

Quality-of-Service (QoS) markings, like the Differentiated Services Code Point (DSCP) and Traffic Class, should be used with care on TCP connections used for encapsulation ๐ŸŽ€. Individual packets SHOULD NOT use different markings than the rest of the connection. Packets with different priorities may be routed differently and cause unnecessary delays in the connection ๐Ÿšฆ.


9.4. Maximum Segment Size

A TCP connection used for IKE encapsulation SHOULD negotiate its MSS so it can avoid unnecessary fragmentation of packets ๐Ÿ“ฆโœจ.


9.5. Tunneling ECN in TCP

When you're using TCP encapsulation, there isn't a one-to-one relationship between outer IP packets and inner ESP/IP messages ๐Ÿ™ƒ. So the markings for Explicit Congestion Notification (ECN) [RFC3168] can't easily be mapped. Still, any ECN Congestion Experienced (CE) marking on inner headers should be preserved through the tunnel ๐ŸŒˆ.

Implementations SHOULD follow the ECN compatibility mode for tunnel ingress as described in [RFC6040]. In compatibility mode, the outer tunnel TCP connection marks its packet headers as not ECN-capable ๐Ÿ’œ.

On egress, if the arriving outer header is marked with CE, the implementation will drop the inner packet ๐Ÿ˜ญ. There isn't a distinct inner packet header to translate the ECN markings onto, so that's just how it goes ๐Ÿ’€.

10. Security Considerations ๐Ÿ”โœจ

Okay bestie, this section is serious, so grab your snacks ๐Ÿ“ IKE Responders that support TCP encapsulation may become vulnerable to new Denial-of-Service (DoS) attacks that are specific to TCP, like SYN-flooding attacks. TCP Responders should be aware of this additional attack surface. ๐Ÿ‘€

TCP connections are also open to RST and other spoofing attacks [RFC4953]. This specification makes IPsec tolerant of sudden TCP connection drops, but if an attacker can tear down TCP connections, the performance of the IPsec connection can suffer, which effectively makes it a DoS attack ๐Ÿ˜ญ

TCP data injection attacks have no effect on application data, since IPsec provides data integrity ๐Ÿ›ก๏ธ However, they can still cause some trouble, mostly by creating DoS attacks:

  • If an attacker alters the content of the Length field that separates packets, then the Receiver will incorrectly identify the boundaries of the following packets and will drop all of them, or even tear down the TCP connection if the content of the Length field happens to be 0 or 1 (see Section 3).
  • If the content of an IKE message is altered, then it will be dropped by the receiver. If the dropped message is the IKE request message, then the Initiator will tear down the IKE SA after some timeout, since in most cases the request message will not be retransmitted (as advised in Section 6.2). Thus, the response will never be received.
  • If an attacker alters the non-ESP marker, then IKE packets will be dispatched to ESP (and sometimes vice versa), and those packets will be dropped.
  • If an attacker modifies the TCP-Encapsulated stream prefix or unencrypted IKE messages before the IKE SA is established, then in most cases this will result in failure to establish the IKE SA, often with false "authentication failed" diagnostics ๐Ÿ™ƒ

[RFC5961] discusses how TCP injection attacks can be mitigated ๐ŸŒธ

Note that data injection attacks are also possible at the IP level (for example, when IP fragmentation is used), resulting in DoS attacks even if TCP encapsulation is not used. On the other hand, TCP injection attacks are easier to pull off than IP fragmentation injection attacks, because TCP keeps a long receive window open that's a sitting target for such attacks ๐ŸŽฏ

If an attacker successfully mounts an injection attack on a TCP connection used for encapsulating IPsec traffic and modifies a Length field, the receiver might not be able to correctly identify the boundaries of the following packets in the stream, since it will try to parse arbitrary data as an ESP or IKE header. After such a parsing failure, all following packets will be dropped. Communication will eventually recover, but this might take several minutes and can result in IKE SA deletion and re-creation. Ugh, not ideal ๐Ÿ’€

To speed up recovery from such attacks, implementations are advised to follow the recommendations in Section 6.1 and to close the TCP connection if incoming packets contain SPIs that don't match any known SAs. Once the TCP connection is closed, it will be re-created by the TCP Originator as described in Section 6.1 ๐Ÿ”

To avoid performance degradation caused by closing and re-creating TCP connections, implementations MAY alternatively try to resync after they receive unknown SPIs. They can do this by searching the TCP stream for a 64-bit binary vector made of a known SPI in the first 32 bits and a valid Sequence Number for that SPI in the second 32 bits. Then they can validate the Integrity Check Value (ICV) of this packet candidate by taking the preceding 16 bits as the Length field. They can also search for 4 bytes of zero (non-ESP marker) followed by 128 bits of IKE SPIs of the IKE SA(s) associated with this TCP connection, and then validate the ICV of this IKE message candidate by taking the 16 bits preceding the non-ESP marker as the Length field. Implementations SHOULD limit the attempts to resync, because if the injection attack is still going, there is a high probability that the resync process will fail or will quickly come under attack again ๐Ÿง 

An attacker capable of blocking UDP traffic can force peers to use TCP encapsulation, which degrades performance and makes the connection more vulnerable to DoS attacks. Note that an attacker who is able to modify packets on the wire, or to block them, can prevent peers from communicating regardless of which transport is being used ๐Ÿšซ

TCP Responders should be careful to make sure the stream prefix IKETCP uniquely identifies incoming streams as streams that use the TCP encapsulation protocol ๐Ÿ”

Attackers may be able to disrupt the TCP connection by sending spurious TCP Reset packets. Therefore, implementations SHOULD make sure that IKE session state persists even if the underlying TCP connection is torn down ๐Ÿ’œ

If MOBIKE is being used, all of the security considerations outlined for MOBIKE apply [RFC4555] โœจ

Similar to MOBIKE, TCP encapsulation requires a TCP Responder to handle changes to source address and port due to network or connection disruption. The successful delivery of valid new IKE or ESP messages over a new TCP connection is how the TCP Responder works out where to send subsequent responses. If an attacker can send packets on a new TCP connection that pass the validation checks of the TCP Responder, they can influence which path future packets take. For this reason, validation of messages on the TCP Responder must include decryption, authentication, and replay checks. Non-negotiable, bestie ๐Ÿซถ


11. IANA Considerations ๐ŸŒท

TCP port 4500 is already allocated to IPsec for NAT traversal in the "Service Name and Transport Protocol Port Number Registry". This port SHOULD be used for TCP-encapsulated IKE and ESP as described in this document ๐Ÿ’…

This document updates the reference for TCP port 4500 from RFC 8229 to itself:

Service Name:  ipsec-nat-t
Port Number / Transport Protocol:  4500/tcp
Description:  IPsec NAT-Traversal
Reference:  RFC 9329

12. References ๐Ÿ“š

12.1. Normative References

[RFC2119]  Bradner, S., "Key words for use in RFCs to Indicate
           Requirement Levels", BCP 14, RFC 2119,
           DOI 10.17487/RFC2119, March 1997,
           <https://www.rfc-editor.org/info/rfc2119>.

[RFC3948]  Huttunen, A., Swander, B., Volpe, V., DiBurro, L., and M.
           Stenberg, "UDP Encapsulation of IPsec ESP Packets",
           RFC 3948, DOI 10.17487/RFC3948, January 2005,
           <https://www.rfc-editor.org/info/rfc3948>.

[RFC4301]  Kent, S. and K. Seo, "Security Architecture for the
           Internet Protocol", RFC 4301, DOI 10.17487/RFC4301,
           December 2005, <https://www.rfc-editor.org/info/rfc4301>.

[RFC4303]  Kent, S., "IP Encapsulating Security Payload (ESP)",
           RFC 4303, DOI 10.17487/RFC4303, December 2005,
           <https://www.rfc-editor.org/info/rfc4303>.

[RFC6040]  Briscoe, B., "Tunnelling of Explicit Congestion
           Notification", RFC 6040, DOI 10.17487/RFC6040, November
           2010, <https://www.rfc-editor.org/info/rfc6040>.

[RFC7296]  Kaufman, C., Hoffman, P., Nir, Y., Eronen, P., and T.
           Kivinen, "Internet Key Exchange Protocol Version 2
           (IKEv2)", STD 79, RFC 7296, DOI 10.17487/RFC7296, October
           2014, <https://www.rfc-editor.org/info/rfc7296>.

[RFC8019]  Nir, Y. and V. Smyslov, "Protecting Internet Key Exchange
           Protocol Version 2 (IKEv2) Implementations from
           Distributed Denial-of-Service Attacks", RFC 8019,
           DOI 10.17487/RFC8019, November 2016,
           <https://www.rfc-editor.org/info/rfc8019>.

[RFC8174]  Leiba, B., "Ambiguity of Uppercase vs Lowercase in RFC
           2119 Key Words", BCP 14, RFC 8174, DOI 10.17487/RFC8174,
           May 2017, <https://www.rfc-editor.org/info/rfc8174>.

12.2. Informative References ๐Ÿ“š๐ŸŽ€

Okay, bestie, this is the extra-credit reading list ๐Ÿ’… (informative, not normative, so these are the background reads that give the whole vibe context โœจ).


Appendix A. Using TCP Encapsulation with TLS ๐Ÿ”โœจ

This section gives you recommendations on how to use TLS alongside TCP encapsulation ๐Ÿ’œ

When you're doing TCP encapsulation, implementations may choose to use TLS 1.2 [RFC5246] or TLS 1.3 [RFC8446] on the TCP connection so they can get past middleboxes that might otherwise block the traffic ๐Ÿ›ก๏ธ.

If a web proxy is sitting on the ports used for the TCP connection and TLS is in use, the TCP Originator can send an HTTP CONNECT message to set up an SA through the proxy [RFC2817] ๐Ÿšช.

The use of TLS should be configurable on the peers, and it may be the default when using TCP encapsulation, or it may be a fallback for when basic TCP encapsulation fails ๐Ÿ’…. The TCP Responder may expect to read encapsulated IKE and ESP packets straight off the TCP connection, or it may expect them inside a stream of TLS data packets. The TCP Originator should be preconfigured on whether or not to use TLS when talking to a given port on the TCP Responder ๐ŸŽ€.

When new TCP connections get re-established after a broken connection, TLS must be renegotiated. TLS session resumption is recommended to improve efficiency in this case ๐Ÿ”.

The security of the IKE session is entirely derived from the IKE negotiation and key establishment, and not from the TLS session (which, in this context, is only used for encapsulation purposes) ๐Ÿ”’ Therefore, when TLS is used on the TCP connection, both the TCP Originator and the TCP Responder SHOULD allow the NULL cipher to be selected for performance reasons. Note that TLS 1.3 only supports AEAD algorithms, and at the time of writing this document there was no recommended cipher suite for TLS 1.3 with the NULL cipher. It is RECOMMENDED to follow [RFC9325] when selecting parameters for TLS ๐Ÿง.

Implementations should be aware that the use of TLS introduces another layer of overhead, which means it takes more bytes to transmit a given IKE and IPsec packet ๐Ÿ˜ญ. For this reason, direct ESP, UDP encapsulation, or TCP encapsulation without TLS should be preferred in situations where TLS is not required in order to traverse middleboxes ๐ŸŒธ.


Appendix B. Example Exchanges of TCP Encapsulation with TLS 1.3 ๐Ÿฆ‹

This appendix has examples of data flows where TCP encapsulation of IKE and IPsec packets is used with TLS 1.3 ๐Ÿงš. They're provided for illustrative purposes only, so readers should go to the main body of the document for the details ๐Ÿ“–.

B.1. Establishing an IKE Session ๐ŸŒˆ

              Client                              Server
            ----------                          ----------
 1)  --------------------  TCP Connection  -------------------
     (IP_I:Port_I  -> IP_R:Port_R)
     TcpSyn                   ------->
                              <-------              TcpSyn,Ack
     TcpAck                   ------->
 2)  ---------------------  TLS Session  ---------------------
     ClientHello              ------->
                                                   ServerHello
                                         {EncryptedExtensions}
                                                {Certificate*}
                                          {CertificateVerify*}
                              <-------              {Finished}
     {Finished}               ------->
 3)  ---------------------- Stream Prefix --------------------
     "IKETCP"                 ------->
 4)  ----------------------- IKE Session ---------------------
     Length + Non-ESP Marker  ------->
     IKE_SA_INIT
     HDR, SAi1, KEi, Ni,
     [N(NAT_DETECTION_SOURCE_IP)],
     [N(NAT_DETECTION_DESTINATION_IP)]
                              <------- Length + Non-ESP Marker
                                                   IKE_SA_INIT
                                           HDR, SAr1, KEr, Nr,
                                 [N(NAT_DETECTION_SOURCE_IP)],
                             [N(NAT_DETECTION_DESTINATION_IP)]
     Length + Non-ESP Marker  ------->
     first IKE_AUTH
     HDR, SK {IDi, [CERTREQ]
     CP(CFG_REQUEST), IDr,
     SAi2, TSi, TSr, ...}
                              <------- Length + Non-ESP Marker
                                                first IKE_AUTH
                                   HDR, SK {IDr, [CERT], AUTH,
                                          EAP, SAr2, TSi, TSr}
     Length + Non-ESP Marker  ------->
     IKE_AUTH (repeat 1..N times)
     HDR, SK {EAP}
                              <------- Length + Non-ESP Marker
                                  IKE_AUTH (repeat 1..N times)
                                                  HDR SK {EAP}
     Length + Non-ESP Marker  ------->
     final IKE_AUTH
     HDR, SK {AUTH}
                              <------- Length + Non-ESP Marker
                                                final IKE_AUTH
                                 HDR, SK {AUTH, CP(CFG_REPLY),
                                            SA, TSi, TSr, ...}
     -------------- IKE and IPsec SAs Established ------------
     Length + ESP Frame       ------->
  1. The client establishes a TCP connection with the server on port 4500 or on an alternate preconfigured port that the server is listening on ๐Ÿ”Œ.
  2. If configured to use TLS, the client initiates a TLS handshake. During the TLS handshake, the server SHOULD NOT request the client's certificate, since authentication is handled as part of IKE negotiation ๐Ÿค.
  3. The client sends the stream prefix for TCP-encapsulated IKE (Section 4) traffic to signal the beginning of IKE negotiation ๐Ÿšฆ.
  4. The client and server establish an IKE connection. This example shows EAP-based authentication, although any authentication type may be used ๐Ÿซถ.

B.2. Deleting an IKE Session โœจ

okay so this is how you say bye-bye to an IKE session ๐Ÿฅบ๐Ÿ’… The client and server do the whole breakup properly, from the IKE messages all the way down to the TCP connection.

                   Client                              Server
                 ----------                          ----------
     1)  ----------------------- IKE Session ---------------------
         Length + Non-ESP Marker  ------->
         INFORMATIONAL
         HDR, SK {[N,] [D,]
                [CP,] ...}
                                  <------- Length + Non-ESP Marker
                                                     INFORMATIONAL
                                                HDR, SK {[N,] [D,]
                                                        [CP], ...}
     2)  ---------------------  TLS Session  ---------------------
         close_notify             ------->
                                  <-------            close_notify
     3)  --------------------  TCP Connection  -------------------
         TcpFin                   ------->
                                  <-------                     Ack
                                  <-------                  TcpFin
         Ack                      ------->
         --------------------  IKE SA Deleted  -------------------
  1. The client and server exchange informational messages to notify IKE SA deletion.
  2. The client and server negotiate TLS session deletion using TLS CLOSE_NOTIFY.
  3. The TCP connection is torn down.

The deletion of the IKE SA should lead to the disposal of the underlying TLS and TCP state. ๐Ÿซถ

B.3. Re-establishing an IKE Session ๐Ÿ”

when the old TCP connection gets wrecked (hi, TCP Reset ๐Ÿ‘‹), the client has to be the one to put it back together. here's the glow-up, step by step:

                   Client                              Server
                 ----------                          ----------
     1)  --------------------  TCP Connection  -------------------
         (IP_I:Port_I  -> IP_R:Port_R)
         TcpSyn                   ------->
                                  <-------              TcpSyn,Ack
         TcpAck                   ------->
     2)  ---------------------  TLS Session  ---------------------
         ClientHello              ------->
                                                       ServerHello
                                             {EncryptedExtensions}
                                  <-------              {Finished}
         {Finished}               ------->
     3)  ---------------------- Stream Prefix --------------------
         "IKETCP"                 ------->
     4)  <---------------------> IKE/ESP Flow <------------------>
  1. If a previous TCP connection was broken (for example, due to a TCP Reset), the client is responsible for re-initiating the TCP connection. The TCP Originator's address and port (IP_I and Port_I) may be different from the previous connection's address and port. new address, same bestie energy ๐Ÿฆ‹
  2. The client SHOULD attempt TLS session resumption if it has previously established a session with the server.
  3. After TCP and TLS are complete, the client sends the stream prefix for TCP-encapsulated IKE traffic (Section 4).
  4. The IKE and ESP packet flow can resume. If MOBIKE is being used, the Initiator SHOULD send an UPDATE_SA_ADDRESSES message. ๐ŸŒธ

B.4. Using MOBIKE between UDP and TCP Encapsulation ๐Ÿงš

this one is the full main-character arc โœจ MOBIKE moves from UDP to TCP encapsulation when the network decides to be difficult ๐Ÿ™„ every step is in the diagram below:

                     Client                              Server
                   ----------                          ----------
     1)  --------------------- IKE_session ----------------------
         (IP_I1:UDP500 -> IP_R:UDP500)
         IKE_SA_INIT              ------->
         HDR, SAi1, KEi, Ni,
         [N(NAT_DETECTION_SOURCE_IP)],
         [N(NAT_DETECTION_DESTINATION_IP)]
                                  <-------            IKE_SA_INIT
                                               HDR, SAr1, KEr, Nr,
                                     [N(NAT_DETECTION_SOURCE_IP)],
                                 [N(NAT_DETECTION_DESTINATION_IP)]
         (IP_I1:UDP4500 -> IP_R:UDP4500)
         Non-ESP Marker           ------->
         IKE_AUTH
         HDR, SK { IDi, CERT, AUTH,
         SAi2, TSi, TSr,
         N(MOBIKE_SUPPORTED) }
                                  <-------          Non-ESP Marker
                                                          IKE_AUTH
                                        HDR, SK { IDr, CERT, AUTH,
                                                   SAr2, TSi, TSr,
                                             N(MOBIKE_SUPPORTED) }
         <---------------------> IKE/ESP Flow <------------------>
     2)  ------------ MOBIKE Attempt on New Network --------------
         (IP_I2:UDP4500 -> IP_R:UDP4500)
         Non-ESP Marker           ------->
         INFORMATIONAL
         HDR, SK { N(UPDATE_SA_ADDRESSES),
         N(NAT_DETECTION_SOURCE_IP),
         N(NAT_DETECTION_DESTINATION_IP) }
     3)  --------------------  TCP Connection  -------------------
         (IP_I2:Port_I -> IP_R:Port_R)
         TcpSyn                   ------->
                                  <-------              TcpSyn,Ack
         TcpAck                   ------->
     4)  ---------------------  TLS Session  ---------------------
         ClientHello              ------->
                                                       ServerHello
                                             {EncryptedExtensions}
                                                    {Certificate*}
                                              {CertificateVerify*}
                                  <-------              {Finished}
         {Finished}               ------->
     5)  ---------------------- Stream Prefix --------------------
         "IKETCP"                 ------->


     6)  ------------ Retransmit Message from step 2 -------------
         Length + Non-ESP Marker  ------->
         INFORMATIONAL
         HDR, SK { N(UPDATE_SA_ADDRESSES),
         N(NAT_DETECTION_SOURCE_IP),
         N(NAT_DETECTION_DESTINATION_IP) }
                                  <------- Length + Non-ESP Marker
                                                     INFORMATIONAL
                             HDR, SK { N(NAT_DETECTION_SOURCE_IP),
                                 N(NAT_DETECTION_DESTINATION_IP) }
     7)  -- New Exchange with recalculated  NAT_DETECTION_*_IP ---
         Length + Non-ESP Marker  ------->
         INFORMATIONAL
         HDR, SK { N(UPDATE_SA_ADDRESSES),
         N(NAT_DETECTION_SOURCE_IP),
         N(NAT_DETECTION_DESTINATION_IP) }
                                  <------- Length + Non-ESP Marker
                                                     INFORMATIONAL
                             HDR, SK { N(NAT_DETECTION_SOURCE_IP),
                                 N(NAT_DETECTION_DESTINATION_IP) }
     8)  <---------------------> IKE/ESP Flow <------------------>
  1. During the IKE_AUTH exchange, the client and server exchange MOBIKE_SUPPORTED notify payloads to indicate support for MOBIKE.
  2. The client changes its point of attachment to the network and receives a new IP address. The client attempts to re-establish the IKE session using the UPDATE_SA_ADDRESSES notify payload, but the server does not respond because the network blocks UDP traffic. ๐Ÿšซ
  3. The client brings up a TCP connection to the server in order to use TCP encapsulation.
  4. The client initiates a TLS handshake with the server.
  5. The client sends the stream prefix for TCP-encapsulated IKE traffic (Section 4).
  6. The client sends the UPDATE_SA_ADDRESSES notify payload in the INFORMATIONAL exchange on the TCP-encapsulated connection. Note that this IKE message is the same as the one sent over UDP in step 2; it should have the same message ID and contents.
  7. Once the client receives a response on the TCP-encapsulated connection, it immediately starts a new INFORMATIONAL exchange with an UPDATE_SA_ADDRESSES notify payload and recalculated NAT_DETECTION_*_IP notify payloads in order to get correct information about the presence of NATs.
  8. The IKE and ESP packet flow can resume. and that's the whole comeback ๐Ÿ’–

Acknowledgments ๐Ÿซถ

Thanks to the authors of RFC 8229 (Tommy Pauly, Samy Touati, and Ravi Mantha). Since this document clarifies and obsoletes RFC 8229, most of its text was borrowed from the original document. ๐Ÿ’œ

The following people provided valuable feedback and advice while preparing RFC 8229: Stuart Cheshire, Delziel Fernandes, Yoav Nir, Christoph Paasch, Yaron Sheffer, David Schinazi, Graham Bartlett, Byju Pularikkal, March Wu, Kingwel Xie, Valery Smyslov, Jun Hu, and Tero Kivinen. Special thanks to Eric Kinnear for his implementation work. ๐Ÿ‘‘

The authors would like to thank Tero Kivinen, Paul Wouters, Joseph Touch, and Christian Huitema for their valuable comments while preparing this document. ๐ŸŒˆ

Authors' Addresses ๐Ÿ’Œ

Tommy Pauly
Apple Inc.
1 Infinite Loop
Cupertino, California 95014
United States of America
Email: tpauly@apple.com
Valery Smyslov
ELVIS-PLUS
PO Box 81
Moscow (Zelenograd)
124460
Russian Federation
Phone: +7 495 276 0211
Email: svan@elvis.ru
๐Ÿ“ฆ where this page comes from