RFC 8229

TCP Encapsulation of IKE and IPsec Packets

πŸ“… published August 2017, from ietf

RFC 8229: TCP Encapsulation of IKE and IPsec Packets πŸŽ€

okay bestie, this is the RFC that lets IPsec and IKE sneak through networks that block UDP, and I'm obsessed 😭✨

Title block: this is RFC 8229 πŸ¦‹, written by T. Pauly (Apple Inc.), S. Touati (Ericsson), and R. Mantha (Cisco Systems). It's a Standards Track doc, published in August 2017, with ISSN 2070-1721. The header doesn't list any obsoletes or updates lines, so it doesn't claim to replace or update anything else πŸ’…


Abstract 🌸

okay so this doc explains how to carry Internet Key Exchange (IKE) and IPsec packets over a TCP connection 🧚. The point is getting past middleboxes that might block IKE negotiation over UDP. The method is called "TCP encapsulation," and it sends both the IKE packets used to set up Security Associations and the Encapsulating Security Payload (ESP) packets over one TCP connection. It's meant to be a fallback option, for when IKE can't be negotiated over UDP. bestie, it's a backup plan and it knows it πŸ’–


Status of This Memo πŸ“œ

this is an Internet Standards Track document πŸ”₯

it's a product of the Internet Engineering Task Force (IETF) and represents the consensus of the IETF community. it got public review and was approved for publication by the Internet Engineering Steering Group (IESG). if you want more on Internet Standards, check out Section 2 of RFC 7841 🫢

for the current status, any errata, and how to send feedback, go to http://www.rfc-editor.org/info/rfc8229 🌈


the IETF Trust and the document authors own the copyright, 2017, all rights reserved πŸ™ˆ

this doc is subject to BCP 78 and the IETF Trust's Legal Provisions Relating to IETF Documents (http://trustee.ietf.org/license-info) as they stand on the publication date. please actually read them, because they explain your rights and restrictions for this document πŸ’œ

if you pull Code Components out of this document, they need to include Simplified BSD License text, as described in Section 4.e of the Trust Legal Provisions. they come with no warranty, same as the Simplified BSD License says πŸ’…


Table of Contents πŸ“

1. Introduction ....................................................3
   1.1. Prior Work and Motivation ..................................4
   1.2. Terminology and Notation ...................................5
2. Configuration ...................................................5
3. TCP-Encapsulated Header Formats .................................6
   3.1. TCP-Encapsulated IKE Header Format .........................6
   3.2. TCP-Encapsulated ESP Header Format .........................7
4. TCP-Encapsulated Stream Prefix ..................................7
5. Applicability ...................................................8
   5.1. Recommended Fallback from UDP ..............................8
6. Connection Establishment and Teardown ...........................9
7. Interaction with NAT Detection Payloads ........................11
8. Using MOBIKE with TCP Encapsulation ............................11
9. Using IKE Message Fragmentation with TCP Encapsulation .........12
10. Considerations for Keep-Alives and Dead Peer Detection ........12
11. Middlebox Considerations ......................................12
12. Performance Considerations ....................................13
   12.1. TCP-in-TCP ...............................................13
   12.2. Added Reliability for Unreliable Protocols ...............14
   12.3. Quality-of-Service Markings ..............................14
   12.4. Maximum Segment Size .....................................14
   12.5. Tunneling ECN in TCP .....................................14
13. Security Considerations .......................................15
14. IANA Considerations ...........................................16
15. References ....................................................16
   15.1. Normative References .....................................16
   15.2. Informative References ...................................17

Appendix A. Using TCP Encapsulation with TLS ......................18
Appendix B. Example Exchanges of TCP Encapsulation with TLS .......19
  B.1. Establishing an IKE Session ................................19
  B.2. Deleting an IKE Session ....................................21
  B.3. Re-establishing an IKE Session .............................22
  B.4. Using MOBIKE between UDP and TCP Encapsulation .............23
Acknowledgments ...................................................25
Authors' Addresses ................................................25

1. Introduction ✨

okay so the Internet Key Exchange Protocol version 2 (IKEv2) [RFC7296] is how you set up IPsec Security Associations (SAs). it sends IKE messages over UDP for control traffic, and uses Encapsulating Security Payload (ESP) [RFC4303] messages for the encrypted data πŸ”

here's the problem. lots of middleboxes on public hotspots block all UDP traffic, IKE and IPsec included, but they let TCP connections through because those look like web traffic πŸ™ˆ so devices that need IPsec are stuck. that includes getting into private enterprise networks, routing Voice over IP calls to carrier networks, or just following security policies. they can't set up IPsec SAs at all 😭

this doc defines a way to wrap IKE control messages and IPsec data messages inside a TCP connection. it's giving problem solved πŸ’–

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

  1. Direct. IKE negotiations start over UDP port 500. if no Network Address Translation (NAT) device is detected between the Initiator and the Responder, the later IKE packets go over UDP port 500, and the IPsec data packets go over ESP 🧚
  2. UDP Encapsulation [RFC3948]. if a NAT is detected between the Initiator and the Responder, the later IKE packets go over UDP port 4500 with four bytes of zero at the start of the UDP payload. ESP packets go out over UDP port 4500 too. some peers default to UDP encapsulation even with no NAT on the path, because some middleboxes don't support IP protocols other than TCP and UDP 🌸
  3. TCP Encapsulation. if the other two aren't available or aren't appropriate, IKE negotiation packets and ESP packets can both go over a single TCP connection to the peer πŸ¦‹
ngl the performance vibes matter here. direct use of ESP or UDP encapsulation should be preferred by IKE implementations, because TCP encapsulation has performance concerns (see Section 12). most implementations should use TCP encapsulation only on networks where negotiation over UDP was tried without getting responses from the peer, or where the network is known not to support UDP πŸ’…

1.1. Prior Work and Motivation 🌈

encapsulating IKE connections inside TCP streams is a common way to deal with network middleboxes blocking UDP packets. the specific goals of this doc are:

  • to promote interoperability by defining a standard method of framing IKE and ESP messages within TCP streams 🀝
  • to be compatible with the current IKEv2 standard without needing modifications or extensions πŸ’–
  • to use IKE over UDP by default, so you avoid the overhead of other alternatives that always rely on TCP or Transport Layer Security (TLS) [RFC5246] 🫢

some previous alternatives are:

Cellular Network Access. Interworking Wireless LAN (IWLAN) uses IKEv2 to set up secure connections to cellular carrier networks, so you can make voice calls and reach other network services over Wi-Fi. 3GPP has recommended that IKEv2 and ESP packets be sent inside 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. messy but it exists πŸ™ˆ

Secure Sockets Layer (SSL) VPNs. lots of proprietary VPN solutions combine TLS and IPsec for reliability. they often run on TCP port 443 πŸ‘‘

IKEv2 over TCP. IKEv2 over TCP, as described in [IKE-over-TCP], is used to avoid UDP fragmentation ✨

1.2. Terminology and Notation πŸ“

this doc separates two things: the IKE peer that starts the TCP connections used for TCP encapsulation, and the Initiator and Responder roles 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 Initiator of the TCP connection is still the one responsible for tearing it down and setting it up again if needed 🧚 so this doc uses the term "TCP Originator" for the IKE peer that starts TCP connections. the peer that receives them is the "TCP Responder." if an IKE SA gets rekeyed one or more times, the TCP Originator MUST stay the peer that originally started 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 πŸ’…

the main reason to use TCP encapsulation is that UDP traffic might be totally blocked on a network. because of that, support for TCP encapsulation isn't negotiated in the IKE exchange πŸ™…β€β™€οΈ instead, support for TCP encapsulation has to be pre-configured on both the TCP Originator and the TCP Responder ✨

implementations MUST support TCP encapsulation on TCP port 4500, which is reserved for IPsec NAT traversal πŸ¦‹

beyond a flag that says the peer supports TCP encapsulation, the configuration for each peer can include these optional parameters:

  • alternate TCP ports where the specific TCP Responder listens for incoming connections. the TCP Originator can start TCP connections to the TCP Responder from any local port 🌸
  • an extra framing protocol to run 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 12), implementations SHOULD prefer ESP direct or UDP-encapsulated SAs over TCP-encapsulated SAs when possible. πŸ’–

3. TCP-Encapsulated Header Formats ✨

okay so UDP encapsulation uses the first four bytes of a message to tell IKE and ESP apart, and TCP encapsulation does the same thing πŸ’… but it also adds a Length field so the receiver knows where each message ends inside the stream 🧚 The length goes in a 16-bit field in front of every message. 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. And Authentication Header (AH) messages are not supported for TCP encapsulation πŸ’€

A TCP stream can technically carry super long messages, but implementations SHOULD limit message lengths to typical UDP datagram ESP payload lengths πŸŽ€ The maximum message length gets used as the effective MTU for connections that are encrypted with ESP, so it affects the characteristics of the inner connections, like the TCP Maximum Segment Size (MSS). Main character energy for the length limit, honestly πŸ‘‘

This way of encapsulating also works for putting IKE and ESP messages inside any protocol that gives you a stream abstraction, not just TCP πŸ¦‹

3.1. TCP-Encapsulated IKE Header 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 header [RFC7296]                     ~
|                                                               |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

Figure 1

The IKE header comes after a 16-bit Length field in network byte order 🌸 That field says how long the IKE message is inside the TCP stream, and the length includes the non-ESP marker. Same as IKE over UDP port 4500, there's a zeroed 32-bit non-ESP marker sitting right before the IKE header. Its whole job is to keep this traffic separate from ESP traffic between the same addresses and ports πŸ”

  • Length (2 octets, unsigned integer) - Length of the IKE packet, including the Length field and non-ESP marker.

3.2. TCP-Encapsulated ESP Header 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 header [RFC4303]                      ~
|                                                               |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

Figure 2

The ESP header gets a 16-bit Length field in front of it too, network byte order, telling you how long the ESP packet is inside 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.

4. TCP-Encapsulated Stream Prefix

Every stream of bytes used for IKE and IPsec encapsulation MUST begin with a fixed six-byte magic value, the characters "IKETCP" as ASCII values πŸͺ„ It's there to identify and validate that the TCP connection is being used for TCP encapsulation as this document defines it. That matters because loads of earlier non-standard protocols were already using TCP port 4500, so this avoids mixing them up πŸ‘€ The value is only sent once, by the TCP Originator only, at the very start of any stream of IKE and ESP messages. One and done, bestie 🫢

If other framing protocols get used on top of 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 inside that added protocol layer (Appendix A). Some framing protocols can negotiate inner protocols, but the stream prefix should always be used so implementations stay as generic as possible and don't depend on other framing protocols sitting on top of TCP πŸ’œ

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

Figure 3

5. Applicability

TCP encapsulation only applies when it's been configured for use with specific IKE peers 🎯 If a Responder is configured to use TCP encapsulation, it MUST listen on the configured port(s) in case any peers start new IKE sessions. Initiators MAY use TCP encapsulation for any IKE session to a peer that's configured to support it. It is recommended that Initiators should only use TCP encapsulation when traffic over UDP is blocked πŸ›‘οΈ

Support for TCP encapsulation is a configured property, not a negotiated one. So it is recommended that if there are multiple IKE endpoints representing a single peer (like several machines with different IP addresses when you connect by Fully Qualified Domain Name, or endpoints used with IKE redirection), all of those endpoints equally support TCP encapsulation 🌈

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 until IKEv2 Mobility and Multihoming (MOBIKE) is used to change the SA endpoints and/or the encapsulation protocol. See Section 8 for more details on using MOBIKE to transition between encapsulation modes ✨

UDP is the preferred transport for IKE messages, so implementations that use TCP encapsulation should have an algorithm for deciding when to switch to TCP after finding out UDP is unusable πŸ¦‹ If an Initiator has no prior knowledge about the network it's on and the status of UDP there, it SHOULD always attempt to negotiate IKE over UDP first. IKEv2 defines how retransmission timers work with IKE messages and, specifically, IKE_SA_INIT messages [RFC7296] 🧠 Generally that means the implementation defines how often to retransmit and the maximum number of retransmissions allowed before it marks the IKE SA as failed. An implementation can try negotiating over TCP once it has hit the maximum retransmissions over UDP, or slightly before, to cut down on 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 🫧

6. Connection Establishment and Teardown ✨

Okay bestie, so when the IKE Initiator uses TCP encapsulation, it opens a TCP connection to the Responder on the configured TCP port πŸ’– The very first bytes on that stream MUST be the stream prefix value (Section 4). After the prefix, the encapsulated IKE messages negotiate the IKE SA and the initial Child SA [RFC7296]. From there, both encapsulated IKE (Figure 1) and ESP (Figure 2) messages travel over the TCP connection πŸ¦‹ 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 is only sent once, and only the TCP Originator sends it 🌸

To close an IKE session, either the Initiator or the Responder SHOULD gracefully tear down the IKE SAs with DELETE payloads πŸ’… Once the SA is deleted, the TCP Originator SHOULD close the TCP connection, unless it wants to reuse that connection for another IKE session to the TCP Responder. If the connection just sits there idle and the TCP Responder needs to clean up resources, the TCP Responder MAY close the TCP connection 🧹

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 was sent, both sides SHOULD keep the state for their SAs for the standard lifetime or timeout period. The TCP Originator is the one responsible for re-establishing the TCP connection if it gets torn down for any unexpected reason 🫢 New TCP connections can use different ports because of NAT mappings or local port allocation changes, so the TCP Responder MUST allow packets for existing SAs to be received from new source ports. That's the kind of flexibility that's giving main character energy πŸ‘‘

A peer MUST discard a partially received message if 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. It's the same behaviour as the initial TCP connection, so no surprises πŸŽ€

If a TCP connection is being used to resume a previous IKE session, the TCP Responder can recognize the session by either the IKE SPI from an encapsulated IKE message or the ESP SPI from an encapsulated ESP message πŸ” If the session was fully established before, it is suggested that the TCP Originator send an UPDATE_SA_ADDRESSES message when MOBIKE is supported, or an informational message (a keep-alive) otherwise πŸ’œ

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 the TCP Responder detects corruption on a connection that was started with a valid stream prefix, it SHOULD close the TCP connection. The connection counts as 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 ESP message with a known SPI fails πŸ’€ Implementations SHOULD NOT tear down a connection just because a single ESP message has an unknown SPI, since the SPI databases may be momentarily out of sync πŸ™ˆ If the problem is instead 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. Not the TCP connection, babe, the IKE SA πŸ’…

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 any firewall or NAT mappings allocated for the TCP connection apply to all of the traffic for that IKE SA equally ✨

Similarly, a TCP Responder SHOULD, at any given time, send packets for an IKE SA and its Child SAs over only one TCP connection. 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 must be successfully decrypted and authenticated, must not be a retransmission of a previously received message, and must be within the expected window for IKE message IDs. An ESP message must pass authentication checks and be decrypted, and must not be a replay of a previous message πŸ”

Since a connection may break and a new one 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 TCP Originator closes the old one πŸ¦‹ A TCP Responder MAY close a TCP connection that it sees as idle and extraneous (one that was previously used for IKE and ESP messages but has been replaced by a new connection) 🧚

Multiple IKE SAs MUST NOT share a single TCP connection, unless one is a rekey of an existing IKE SA. In that case there will temporarily be two IKE SAs on the same TCP connection, and that's the only exception 🌈


7. Interaction with NAT Detection Payloads πŸ•΅οΈβ€β™€οΈ

When negotiating over UDP port 500, 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 SHOULD use the applicable TCP ports when creating and checking the SHA-1 digests πŸŽ€

If a NAT is detected because the SHA-1 digests don't match the expected values, no change should be made to how subsequent IKE or ESP packets get encapsulated, since TCP encapsulation inherently supports NAT traversal 🌸 Implementations MAY use the information that a NAT is present to influence keep-alive timer values ⏰

If a NAT is detected, implementations need to handle transport mode TCP and UDP packet checksum fixup as defined for UDP encapsulation in [RFC3948] 🧷


8. Using MOBIKE with TCP Encapsulation πŸ“±

When an IKE session that has negotiated MOBIKE [RFC4555] is moving between networks, the Initiator of the transition may switch between TCP encapsulation, UDP encapsulation, or no encapsulation πŸ¦‹ Implementations that implement both MOBIKE and TCP encapsulation MUST support dynamically enabling and disabling TCP encapsulation as interfaces change. Hello, flexibility πŸ’…

When a MOBIKE-enabled Initiator changes networks, the UPDATE_SA_ADDRESSES notification SHOULD be sent out first over UDP, before trying over TCP πŸš€ If there is a response to the UPDATE_SA_ADDRESSES notification 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), regardless of whether a connection on a previous network was using TCP encapsulation. Similarly, if the Responder only responds to the UPDATE_SA_ADDRESSES notification 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 🌈


9. Using IKE Message Fragmentation with TCP Encapsulation 🧩

IKE message fragmentation [RFC7383] is not required when using TCP encapsulation, since a TCP stream already handles fragmenting its contents across packets πŸ₯° Because fragmentation is redundant in this case, implementations might choose not to negotiate IKE fragmentation. Even if fragmentation is negotiated, an implementation SHOULD NOT send fragments when going over a TCP connection, although it MUST support receiving fragments. It's giving "do it, but don't use it" energy πŸ˜‚

If an implementation supports both MOBIKE and IKE fragmentation, it SHOULD negotiate IKE fragmentation over a TCP-encapsulated session, just in case the session switches to UDP encapsulation on another network πŸ¦‹


10. Considerations for Keep-Alives and Dead Peer Detection πŸ’“

Encapsulating IKE and IPsec inside a TCP connection can change the strategy implementations use to detect peer liveness and to maintain middlebox port mappings 🧐 Peer liveness should be checked using IKE informational packets [RFC7296].

In general, TCP port mappings are kept by NATs for longer than UDP port mappings, so IPsec ESP NAT keep-alives [RFC3948] SHOULD NOT be sent when using TCP encapsulation πŸ’€ Any implementation using TCP encapsulation MUST silently drop incoming NAT keep-alive packets and must not treat them as errors. NAT keep-alive packets over a TCP-encapsulated IPsec connection are sent as an ESP message with a one-octet-long payload with the value 0xFF πŸ§šβ€β™€οΈ

Note that, depending on how TCP and TLS are configured on the connection, TCP keep-alives [RFC1122] and TLS keep-alives [RFC6520] may be used. These MUST NOT be used as indications of IKE peer liveness. Not a vibe, not a signal, don't use them for that πŸš«πŸ’œ


11. Middlebox Considerations πŸ›‘οΈ

Lots of security networking devices, like firewalls, intrusion prevention systems, network optimization/acceleration devices, and NAT devices, keep the state of sessions that pass through them πŸ‘€

These devices commonly track transport-layer and/or application-layer data so they can drop traffic that's anomalous or malicious in nature 🚨 While many of them are more likely to pass TCP-encapsulated traffic than UDP-encapsulated traffic, 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, such as TCP sequence numbers. So TCP encapsulation of IKE should use standard TCP behaviors to avoid being dropped by middleboxes 🧠✨


12. Performance Considerations 🏎️

Several aspects of TCP encapsulation for IKE and IPsec packets may negatively impact the performance of connections within a tunnel-mode IPsec SA πŸ“‰ Implementations should be aware of these performance impacts and take them into consideration when deciding when to use TCP encapsulation. Implementations SHOULD favor using direct ESP or UDP encapsulation over TCP encapsulation whenever possible 🫢🌷

12.1. TCP-in-TCP 🧚

Okay so if the outer connection between IKE peers is over TCP, the inner TCP connections can get kinda messy 😭. Running TCP within TCP is discouraged, bestie, because TCP's algorithms generally assume they're running over an unreliable datagram layer πŸ’€.

If the outer (tunnel) TCP connection loses a packet, the inner connections never see the loss 🫣. The outer connection just retransmits to cover it. Since the outer connection delivers the inner messages in order, anything after a lost packet might have to wait until that loss is fixed. So from the inner connections' point of view, loss on the outer connection just looks like delay ⏳. The inner traffic also gets burstier, because a big pile of inner packets can get delivered through the tunnel all at once 🌊. The inner TCP connection might read a long wait as a transmission problem and hit a retransmission timeout, which causes spurious retransmissions πŸ™ƒ. If those retransmissions don't get detected as spurious in time, the inner sending rate can drop more than it needs to πŸ“‰.

The inner connection's round-trip-time estimate is also affected by the outer connection's burstiness whenever the outer connection has long delays while retransmitting packets ⏱️. That makes the inner congestion control loop less reactive, and it could end up stuck at a lower sending rate than the outer TCP would actually allow 😀.

TCP-in-TCP can also cause extra buffering, aka bufferbloat 🫧. This happens when the outer connection's window size shrinks and ends up smaller than the window sizes of the inner connections. Then packets start piling up in the outer connection's send buffers. To keep this under control, the outer TCP connection should have limits on its send buffer size and on how fast it reduces its window size πŸŽ€.

Any negative effects get shared by every flow going through the outer TCP connection, so this is a big deal for latency-sensitive or real-time apps using the tunnel 🎧. If that kind of traffic is riding a TCP-encapsulated IPsec connection, it is recommended that the number of inner connections sharing the tunnel be limited as much as possible 🫢.

12.2. Added Reliability for Unreliable Protocols πŸ’œ

ESP is an unreliable protocol, so sending ESP packets over a TCP connection totally changes how those packets behave πŸ”„. Some application-level protocols that would rather lose a packet than wait for it, like Voice over IP or other real-time protocols, can get hurt if the TCP connection retransmits their packets after a loss 😩.

12.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 get routed differently, and that can cause unnecessary delays in the connection 🐒.

12.4. Maximum Segment Size πŸ“

A TCP connection used for IKE encapsulation SHOULD negotiate its MSS so it can avoid unnecessary fragmentation of packets 🧩.

12.5. Tunneling ECN in TCP 🌈

There isn't a one-to-one relationship between outer IP packets and inner ESP/IP messages when you use TCP encapsulation, so the Explicit Congestion Notification (ECN) [RFC3168] markings can't just be mapped straight across πŸ—ΊοΈ. 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. If the arriving outer header is marked with CE on egress, the implementation will drop the inner packet, because there's no separate inner packet header to translate the ECN markings onto πŸ’€.

13. Security Considerations πŸ”

IKE Responders that support TCP encapsulation might 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 extra attack surface, bestie πŸ‘€.

TCP Responders should be careful to make sure that (1) the stream prefix "IKETCP" uniquely identifies incoming streams as streams that use the TCP encapsulation protocol and (2) they aren't running any other protocols on the same listening port, so nothing conflicts 🚧.

Attackers may be able to disrupt the TCP connection by sending spurious TCP Reset packets πŸ™…β€β™€οΈ. So implementations SHOULD make sure that IKE session state persists even if the underlying TCP connection gets torn down πŸ›‘οΈ.

If MOBIKE is being used, all of the security considerations outlined for MOBIKE apply [RFC4555] πŸ“Ž.

Like MOBIKE, TCP encapsulation requires a TCP Responder to handle changes to source address and port caused by network or connection disruption πŸ”. The TCP Responder uses the successful delivery of valid IKE or ESP messages over a new TCP connection to figure out where to send later responses πŸ“¬. If an attacker can send packets on a new TCP connection that pass the TCP Responder's validation checks, the attacker can influence which path future packets take 🚨. That's why the validation of messages on the TCP Responder must include decryption, authentication, and replay checks πŸ”’.

Since TCP provides reliable, in-order delivery of ESP messages, the ESP anti-replay window size SHOULD be set to 1. See [RFC4303] for a complete description of the ESP anti-replay window πŸ“–. This makes implementations more protected against replay attacks 🫢.

14. IANA Considerations πŸ“‹

TCP port 4500 is already allocated to IPsec for NAT traversal 🌐. 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:

      Keyword       Decimal    Description           Reference
      -----------   --------   -------------------   ---------
      ipsec-nat-t   4500/tcp   IPsec NAT-Traversal   RFC 8229

                              Figure 4

15. References πŸ“š

15.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,
           <http://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,
           <http://www.rfc-editor.org/info/rfc3948>.

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

[RFC6040]  Briscoe, B., "Tunnelling of Explicit Congestion
           Notification", RFC 6040, DOI 10.17487/RFC6040,
           November 2010, <http://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, <http://www.rfc-editor.org/info/rfc7296>.

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

15.2. Informative References πŸ”

[IKE-over-TCP]
           Nir, Y., "A TCP transport for the Internet Key Exchange",
           Work in Progress, draft-ietf-ipsecme-ike-tcp-01,
           December 2012.

[RFC1122]  Braden, R., Ed., "Requirements for Internet Hosts -
           Communication Layers", STD 3, RFC 1122,
           DOI 10.17487/RFC1122, October 1989,
           <http://www.rfc-editor.org/info/rfc1122>.

[RFC2817]  Khare, R. and S. Lawrence, "Upgrading to TLS Within
           HTTP/1.1", RFC 2817, DOI 10.17487/RFC2817, May 2000,
           <http://www.rfc-editor.org/info/rfc2817>.

[RFC3168]  Ramakrishnan, K., Floyd, S., and D. Black, "The Addition
           of Explicit Congestion Notification (ECN) to IP",
           RFC 3168, DOI 10.17487/RFC3168, September 2001,
           <http://www.rfc-editor.org/info/rfc3168>.

[RFC4555]  Eronen, P., "IKEv2 Mobility and Multihoming Protocol
           (MOBIKE)", RFC 4555, DOI 10.17487/RFC4555, June 2006,
           <http://www.rfc-editor.org/info/rfc4555>.

[RFC5246]  Dierks, T. and E. Rescorla, "The Transport Layer Security
           (TLS) Protocol Version 1.2", RFC 5246,
           DOI 10.17487/RFC5246, August 2008,
           <http://www.rfc-editor.org/info/rfc5246>.

[RFC6520]  Seggelmann, R., Tuexen, M., and M. Williams, "Transport
           Layer Security (TLS) and Datagram Transport Layer Security
           (DTLS) Heartbeat Extension", RFC 6520,
           DOI 10.17487/RFC6520, February 2012,
           <http://www.rfc-editor.org/info/rfc6520>.

[RFC7383]  Smyslov, V., "Internet Key Exchange Protocol Version 2
           (IKEv2) Message Fragmentation", RFC 7383,
           DOI 10.17487/RFC7383, November 2014,
           <http://www.rfc-editor.org/info/rfc7383>.

Appendix A. Using TCP Encapsulation with TLS πŸ”’

This section gives recommendations on how to use TLS alongside TCP encapsulation πŸ’Œ.

When you use TCP encapsulation, implementations may choose to use TLS [RFC5246] on the TCP connection so they can traverse middleboxes that might otherwise block the traffic 🧱.

If a web proxy is applied to the ports used for the TCP connection and TLS is being used, the TCP Originator can send an HTTP CONNECT message to establish an SA through the proxy [RFC2817] 🌐.

The use of TLS should be configurable on the peers. It can be the default when using TCP encapsulation, or it can be a fallback for when basic TCP encapsulation fails βš™οΈ. The TCP Responder may expect to read encapsulated IKE and ESP packets directly from the TCP connection, or it may expect to read them from a stream of TLS data packets πŸ“¦. The TCP Originator should be pre-configured to use TLS or not 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, not from the TLS session (which in this context is only used for encapsulation purposes) 🫢. So 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 🏎️.

Implementations should be aware that TLS adds another layer of overhead, so 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 isn't required to traverse middleboxes ✨.

Appendix B. Example Exchanges of TCP Encapsulation with TLS πŸŽ€

B.1. Establishing an IKE Session 🌸

okay bestie, this is the whole glow-up of an IKE session getting started πŸ’– Figure 5 shows the entire thing from start to finish ✨

                   Client                              Server
                 ----------                          ----------
     1)  --------------------  TCP Connection  -------------------
         (IP_I:Port_I  -> IP_R:Port_R)
         TcpSyn                    ---------->
                                   <----------          TcpSyn,Ack
         TcpAck                    ---------->

     2)  ---------------------  TLS Session  ---------------------
         ClientHello               ---------->
                                                       ServerHello
                                                      Certificate*
                                                ServerKeyExchange*
                                   <----------     ServerHelloDone
         ClientKeyExchange
         CertificateVerify*
         [ChangeCipherSpec]
         Finished                  ---------->
                                                [ChangeCipherSpec]
                                   <----------            Finished

     3)  ---------------------- Stream Prefix --------------------
         "IKETCP"                  ---------->
     4)  ----------------------- IKE Session ---------------------
         Length + Non-ESP Marker   ---------->
         IKE_SA_INIT
         HDR, SAi1, KEi, Ni,
         [N(NAT_DETECTION_*_IP)]
                                   <------ Length + Non-ESP Marker
                                                       IKE_SA_INIT
                                               HDR, SAr1, KEr, Nr,
                                           [N(NAT_DETECTION_*_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 + EAP
         repeat 1..N times
                                   <------ Length + Non-ESP Marker
                                                    IKE_AUTH + 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        ---------->

                                 Figure 5
  1. The client sets up a TCP connection with the server on port 4500, or on an alternate pre-configured port that the server is listening on. πŸ¦‹
  2. If it's configured to use TLS, the client starts a TLS handshake. During that handshake, the server SHOULD NOT request the client's certificate, since authentication is already handled as part of IKE negotiation. πŸ”
  3. The client sends the stream prefix for TCP-encapsulated IKE (Section 4) traffic to signal that IKE negotiation is starting. πŸŽ€
  4. The client and server set up an IKE connection. This example shows EAP-based authentication, but any authentication type may be used. ✨

B.2. Deleting an IKE Session πŸ’”

okay so, breaking up with an IKE session is also a whole process, and Figure 6 shows every step πŸ₯€

                   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  -------------------

                                 Figure 6
  1. The client and server swap informational messages to tell each other the IKE SA is being deleted. πŸ“£
  2. The client and server work out TLS session deletion using TLS CLOSE_NOTIFY. 🀝
  3. The TCP connection gets torn down. 🧹

The deletion of the IKE SA should lead to the disposal of the underlying TLS and TCP state. so clean, no leftovers 🫧

B.3. Re-establishing an IKE Session πŸ”„

sometimes the connection drops (hi, TCP Reset πŸ‘‹), and then you need to reconnect. Figure 7 is the comeback arc πŸ‘‘

                   Client                              Server
                 ----------                          ----------
     1)  --------------------  TCP Connection  -------------------
         (IP_I:Port_I  -> IP_R:Port_R)
         TcpSyn                    ---------->
                                   <----------          TcpSyn,Ack
         TcpAck                    ---------->
     2)  ---------------------  TLS Session  ---------------------
         ClientHello               ---------->
                                   <----------         ServerHello
                                                [ChangeCipherSpec]
                                                          Finished
         [ChangeCipherSpec]        ---------->
         Finished
     3)  ---------------------- Stream Prefix --------------------
         "IKETCP"                  ---------->
     4)  <---------------------> IKE/ESP Flow <------------------>
         Length + ESP Frame        ---------->

                                 Figure 7
  1. If a previous TCP connection was broken (for example, due to a TCP Reset), the client is the one responsible for reopening 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. 🌈
  2. In the ClientHello TLS message, the client SHOULD send the session ID it got in the previous TLS handshake, if it has one. It's up to the server to do either an abbreviated handshake or a full handshake, based on whether the session ID matches. πŸͺͺ
  3. Once TCP and TLS are done, the client sends the stream prefix for TCP-encapsulated IKE traffic (Section 4). πŸŽ€
  4. The IKE and ESP packet flow can pick back up. 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 giving full main character energy 🌟 the client starts on UDP, then has to switch over to TCP mid-session, and Figure 8 shows the whole switch 🎬

                     Client                              Server
                   ----------                          ----------
         (IP_I1:UDP500 -> IP_R:UDP500)
     1)  ----------------- IKE_SA_INIT Exchange -----------------
         (IP_I1:UDP4500 -> IP_R:UDP4500)
         Non-ESP Marker           ----------->
         Initial IKE_AUTH
         HDR, SK { IDi, CERT, AUTH,
         CP(CFG_REQUEST),
         SAi2, TSi, TSr,
         N(MOBIKE_SUPPORTED) }
                                  <-----------      Non-ESP Marker
                                                  Initial IKE_AUTH
                                        HDR, SK { IDr, CERT, AUTH,
                                              EAP, SAr2, TSi, TSr,
                                             N(MOBIKE_SUPPORTED) }
         <------------------ IKE SA Establishment --------------->

     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
                                                      Certificate*
                                                ServerKeyExchange*
                                  <-----------     ServerHelloDone
         ClientKeyExchange
         CertificateVerify*
         [ChangeCipherSpec]
         Finished                 ----------->
                                                [ChangeCipherSpec]
                                  <-----------            Finished

     5)  ---------------------- Stream Prefix --------------------
         "IKETCP"                  ---------->

     6)  ----------------------- IKE Session ---------------------
         Length + Non-ESP Marker  ----------->
         INFORMATIONAL (Same as step 2)
         HDR, SK { N(UPDATE_SA_ADDRESSES),
         N(NAT_DETECTION_SOURCE_IP),
         N(NAT_DETECTION_DESTINATION_IP) }

                                  <------- Length + Non-ESP Marker
                             HDR, SK { N(NAT_DETECTION_SOURCE_IP),
                                 N(NAT_DETECTION_DESTINATION_IP) }
     7)  <----------------- IKE/ESP Data Flow ------------------->

                                 Figure 8
  1. During the IKE_SA_INIT exchange, the client and server swap MOBIKE_SUPPORTED notify payloads to show they support MOBIKE. 🀳
  2. The client switches to a new network and gets a new IP address. It tries to re-establish the IKE session using the UPDATE_SA_ADDRESSES notify payload, but the server never answers because the network blocks UDP traffic. πŸ™ˆ
  3. The client opens a TCP connection to the server so it can use TCP encapsulation. 🧦
  4. The client starts 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 over the TCP-encapsulated connection. This IKE message is the exact same one sent over UDP in step 2, so it should have the same message ID and contents. πŸ”
  7. The IKE and ESP packet flow can resume. πŸ₯³

Acknowledgments 🫢

the authors shouted out everyone who helped with input and advice: 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 the implementation work πŸ‘‘πŸ’–

Authors' Addresses πŸ’Œ

Tommy Pauly 🍎

Apple Inc.
1 Infinite Loop
Cupertino, California  95014
United States of America

Email: tpauly@apple.com

Samy Touati 🌷

Ericsson
2755 Augustine
Santa Clara, California  95054
United States of America

Email: samy.touati@ericsson.com

Ravi Mantha 🌈

Cisco Systems
SEZ, Embassy Tech Village
Panathur, Bangalore  560 037
India

Email: ramantha@cisco.com
πŸ“¦ where this page comes from