RFC 6062

Traversal Using Relays around NAT (TURN) Extensions for TCP Allocations

πŸ“… published November 2010, from ietf

Title Block πŸŽ€

RFC 6062 πŸ’– is an official IETF document, with the title Traversal Using Relays around NAT (TURN) Extensions for TCP Allocations ✨

  • Authors: S. Perreault, Ed. (Viagenie) and J. Rosenberg (jdrosen.net). The "Ed." means Perreault is the editor 🫢
  • Category: Standards Track, so this is a real spec that implementers are supposed to follow πŸ’…
  • ISSN: 2070-1721
  • Date: November 2010 🌸
  • Obsoletes / Updates: the header doesn't list either one, so it doesn't replace or update any earlier RFC πŸ¦‹

Abstract ✨

okay so this spec extends TURN, which is a relay protocol for NAT traversal 🧚 With this extension, a TURN client can ask for a TCP allocation, and the spec adds new requests and indications so the TURN server can open and accept TCP connections with the client's peers. ngl the vibe is very controlled: TURN and this extension both tightly limit how the relayed address can be used. The big thing is that it stops people from running general-purpose servers on ports they grabbed from the TURN server πŸ™…β€β™€οΈ


Status of This Memo πŸ’œ

This is an Internet Standards Track document, which means it's official πŸ‘‘

It's a product of the Internet Engineering Task Force (IETF), so it represents what the IETF community agreed on. It went through public review and got approved for publication by the Internet Engineering Steering Group (IESG). If you want more info on Internet Standards, check Section 2 of RFC 5741 🌈

For the current status of this document, any errata, and how to send feedback, go to http://www.rfc-editor.org/info/rfc6062 πŸ”₯


Copyright (c) 2010 IETF Trust and the persons identified as the document authors. All rights reserved. πŸ’…

This document is covered by BCP 78 and the IETF Trust's Legal Provisions Relating to IETF Documents (http://trustee.ietf.org/license-info), as they were in effect when it was published. Please actually read these, bestie, because they explain your rights and restrictions for this document πŸ™ˆ

Code Components pulled out of this document have to include the Simplified BSD License text, as described in Section 4.e of the Trust Legal Provisions. They come with no warranty, as the Simplified BSD License describes ✨


Table of Contents πŸ¦‹

1.  Introduction . . . . . . . . . . . . . . . . . . . . . . . . .  3
2.  Conventions  . . . . . . . . . . . . . . . . . . . . . . . . .  3
3.  Overview of Operation  . . . . . . . . . . . . . . . . . . . .  4
4.  Client Processing  . . . . . . . . . . . . . . . . . . . . . .  6
  4.1.  Creating an Allocation . . . . . . . . . . . . . . . . . .  6
  4.2.  Refreshing an Allocation . . . . . . . . . . . . . . . . .  7
  4.3.  Initiating a Connection  . . . . . . . . . . . . . . . . .  7
  4.4.  Receiving a Connection . . . . . . . . . . . . . . . . . .  7
  4.5.  Sending and Receiving Data . . . . . . . . . . . . . . . .  8
  4.6.  Data Connection Maintenance  . . . . . . . . . . . . . . .  8
5.  TURN Server Behavior . . . . . . . . . . . . . . . . . . . . .  8
  5.1.  Receiving a TCP Allocate Request . . . . . . . . . . . . .  8
  5.2.  Receiving a Connect Request  . . . . . . . . . . . . . . .  9
  5.3.  Receiving a TCP Connection on a Relayed Transport
        Address  . . . . . . . . . . . . . . . . . . . . . . . . . 10
  5.4.  Receiving a ConnectionBind Request . . . . . . . . . . . . 11
  5.5.  Data Connection Maintenance  . . . . . . . . . . . . . . . 11
6.  IANA Considerations  . . . . . . . . . . . . . . . . . . . . . 11
  6.1.  New STUN Methods . . . . . . . . . . . . . . . . . . . . . 11
  6.2.  New STUN Attributes  . . . . . . . . . . . . . . . . . . . 12
    6.2.1.  CONNECTION-ID  . . . . . . . . . . . . . . . . . . . . 12
  6.3.  New STUN Error Codes . . . . . . . . . . . . . . . . . . . 12
7.  Security Considerations  . . . . . . . . . . . . . . . . . . . 12
8.  Acknowledgements . . . . . . . . . . . . . . . . . . . . . . . 12
9.  References . . . . . . . . . . . . . . . . . . . . . . . . . . 12
  9.1.  Normative References . . . . . . . . . . . . . . . . . . . 12
  9.2.  Informative References . . . . . . . . . . . . . . . . . . 13

1. Introduction ✨

okay so TURN [RFC5766] is an extension to the Session Traversal Utilities for NAT [RFC5389] protocol, which is STUN 🧚 TURN lets clients talk to a TURN server and ask it to allocate ports on one of its host interfaces. Then it relays traffic between that port and the client itself πŸ’– When you pair TURN with STUN and Interactive Connectivity Establishment (ICE) [RFC5245], you get a full NAT traversal solution for UDP-based media sessions πŸŽ€

Here's the plot twist, though: TURN on its own can't give a client a TCP-based port on a TURN server 😭 That's a problem, because sometimes you want a TCP session with a peer and NATs block the direct TCP connection. Two examples are app sharing between desktop softphones and sending pictures during a voice call πŸ“Έ

So this document defines an extension to TURN that lets a client get a TCP allocation πŸ¦‹ With it, the client can start outgoing TCP connections from that allocation to peers, and it can also accept incoming TCP connection requests from peers that are aimed at that allocation. Iconic πŸ‘‘

Quick vocab check: a "TCP allocation" is a TURN allocation that uses TCP as the transport protocol instead of UDP πŸ’… Each one is uniquely identified by its relayed transport address, which is an IP address plus a TCP port (defined in [RFC5766]) ✨

2. Conventions 🌈

Okay, the key words in this document are the ones you'll see in capitals, and they get interpreted as described in [RFC2119] πŸ™ˆ Here's the full list, so you can spot them: "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" πŸ”₯

3. Overview of Operation 🧚

Okay bestie, this is the big picture moment πŸ¦‹ Check out Figure 1:

                                                      +--------+
                                                      |        |
                                                      | Peer1  |
                                                   /  |        |
                                                  /   |        |
                                                 /    +--------+
                                                /
                                               /
                                              / Peer Data 1
                                             /
      +--------+  Control       +--------+  /
      |        | -------------- |        | /
      | Client | Client Data 1  | TURN   |
      |        | -------------- | Server | \
      |        | -------------- |        |  \
      +--------+ Client Data 2  +--------+   \
                                              \
                                               \
                                                \     +--------+
                                                 \    |        |
                                      Peer Data 2 \   | Peer2  |
                                                   \  |        |
                                                      |        |
                                                      +--------+

Figure 1: TURN TCP Model πŸ’œ

So the client has two different types of connections to its TURN server πŸ‘€ For each allocated relayed transport address, there's a single control connection, and that one is used to get allocations and open up new connections. Then, for each connection to a peer, the client has a single connection to its TURN server. Those are called data connections 🌸 So there's a data connection from the client to its TURN server (the client data connection), and one from the TURN server to a peer (the peer data connection). Actual application data gets sent on these. After the first TURN message binds the client data connection to a peer data connection, only application data can be sent, no TURN messaging at all πŸ™…β€β™€οΈ The control connection is the opposite vibe: it only allows TURN messages and not application data. Iconic separation of duties, honestly πŸ’…

To get a TCP-based allocation, a client first opens a TCP or TLS connection to its TURN server. Then it sends an Allocate request over that control connection. That request has a REQUESTED-TRANSPORT attribute, which says a TCP-based allocation is wanted ✨ A server that supports this extension will allocate a TCP relayed transport address and start listening for connection requests on it. Then it hands that relayed transport address back to the client in the response to the Allocate request. The connection the Allocate request was sent on? That's the control connection 🫢

If a client wants to establish a TCP connection to a peer from that relayed transport address, it sends a Connect request to the TURN server over the control connection. That request has an XOR-PEER-ADDRESS attribute identifying the peer IP address and port (aka its "transport address") that the connection is going to. The TURN server tries to open the TCP connection, and if that works, it responds to the Connect request with a success response. The server also creates a connection identifier for this connection and passes it back to the client in that success response. Also, a maximum of one connection to a given peer transport address can be established per allocation, so no doubling up πŸ™ˆ

Note: Establishing a relayed connection from the client to a peer is done in two steps. First, the allocation is created, and second, the connection is established. Combining the two is not desirable for NAT traversal. It's expected that, between the first and second steps, the client will communicate off-band with the peer (e.g., using ICE [RFC5245]) and tell it the relayed transport address that the TURN server allocated and from which it is about to initiate a connection. The peer can then "get ready": open holes in its firewall, try to poke holes in a NAT, attempt a TCP simultaneous open, etc. πŸ¦‹

To actually send data on the new connection, or use it in any way, the client sets up a new TCP connection to its TURN server. Once that's established, it sends a ConnectionBind request to the server over this new connection. That request echoes back the connection identifier, and the TURN server uses it to correlate the two connections 🧩 So the TCP connection to the peer is associated with a TCP connection to the client, one-to-one. Both are now data connections. From here, if the server receives data from the peer, it forwards that data towards the client, with no encapsulation at all. Any data the TURN server gets from the client over the client data connection gets forwarded to the peer, again with no encapsulation or framing of any kind. And once a connection has been bound using the ConnectionBind request, TURN messaging is no longer permitted on it 🚫

Now the reverse situation: when a peer opens a TCP connection towards the relayed transport address, the server checks whether there's a permission in place for that peer. If there isn't one, the connection gets closed πŸ’€ Permissions are created with the CreatePermission request sent over the control connection, just like for UDP TURN. If there is a permission in place, the TURN server sends a ConnectionAttempt Indication to the client over the control connection. That indication contains a connection identifier. Once again, the client opens a separate TCP connection to its TURN server, and over that connection it issues a ConnectionBind request. Once that's received, the TURN server starts relaying data back and forth ⭐ The server closes the peer data connection if no ConnectionBind request shows up after a timeout.

If the client closes a client data connection, the corresponding peer data connection gets closed too. If the peer closes a peer data connection, the corresponding client data connection gets closed. That means the status of the connection is directly known to the client, which is so clean 🧼

The TURN server relays the data between the client and peer data connections. End-to-end flow control is maintained by the relay process: if the relay process can't write data to the destination of the relayed data anymore, it stops reading data from the source. Backpressure, but make it protocol 🌈


4. Client Processing πŸ’…

4.1. Creating an Allocation

To create a TCP allocation, a client MUST initiate a new TCP or TLS connection to its TURN server, identical to the TCP or TLS procedures defined in [RFC5766]. TCP allocations cannot be obtained using a UDP association between client and server πŸ™…β€β™€οΈ

Once set up, a client MUST send a TURN Allocate request. That request MUST contain a REQUESTED-TRANSPORT attribute whose value is 6, corresponding to TCP πŸŽ€

The request MUST NOT include a DONT-FRAGMENT, RESERVATION-TOKEN, or EVEN-PORT attribute. Those features are specific to UDP-based capabilities and aren't utilized by TURN-TCP, so skip them, bestie πŸ™ˆ However, a LIFETIME attribute MAY be included, with semantics identical to the UDP case ⏰

The procedures for authentication of the Allocate request and processing of success and failure responses are identical to those for UDP πŸ”

Once a success response is received, the TCP connection to the TURN server is called the control connection for that allocation 🫢

4.2. Refreshing an Allocation

The procedures for refreshing an allocation are identical to those for UDP. Note that the Refresh MUST be sent on the control connection πŸ”

4.3. Initiating a Connection

To initiate a TCP connection to a peer, a client MUST send a Connect request over the control connection for the desired allocation. The Connect request MUST include an XOR-PEER-ADDRESS attribute containing the transport address of the peer to which a connection is desired 🎯

If the connection is successfully established, the client will receive a success response. That response will contain a CONNECTION-ID attribute. The client MUST initiate a new TCP connection to the server, utilizing the same destination transport address to which the control connection was established. This connection MUST be made using a different local transport address. Authentication of the client by the server MUST use the same method and credentials as for the control connection. Once established, the client MUST send a ConnectionBind request over the new connection. That request MUST include the CONNECTION-ID attribute, echoed from the Connect Success response. When a response to the ConnectionBind request is received, if it is a success, the TCP connection on which it was sent is called the client data connection corresponding to the peer 🌸

If the result of the Connect request was an Error Response, and the response code was 447 (Connection Timeout or Failure), it means that the TURN server was unable to connect to the peer 😭 The client MAY retry with the same XOR-PEER-ADDRESS attribute, but MUST wait at least 10 seconds. Patience is a virtue, babe ⏳

As with any other request, multiple Connect requests MAY be sent simultaneously. However, Connect requests with the same XOR-PEER-ADDRESS parameter MUST NOT be sent simultaneously 🚦

4.4. Receiving a Connection

After an Allocate request is successfully processed by the server, the client will start receiving a ConnectionAttempt indication each time a peer for which a permission has been installed attempts a new connection to the relayed transport address πŸ“¬ This indication will contain CONNECTION-ID and XOR-PEER-ADDRESS attributes. If the client wishes to accept this connection, it MUST initiate a new TCP connection to the server, utilizing the same destination transport address to which the control connection was established. This connection MUST be made using a different local transport address. Authentication of the client by the server MUST use the same method and credentials as for the control connection. Once established, the client MUST send a ConnectionBind request over the new connection. That request MUST include the CONNECTION-ID attribute, echoed from the ConnectionAttempt indication. When a response to the ConnectionBind request is received, if it is a success, the TCP connection on which it was sent is called the client data connection corresponding to the peer πŸ’–

4.5. Sending and Receiving Data

Once a client data connection is established, data sent on it by the client will be relayed as-is to the peer by the server. Similarly, data sent by the peer to the server will be relayed as-is to the client over the data connection πŸ“

4.6. Data Connection Maintenance 🧚

okay so the client MUST refresh the allocation tied to a data connection, using the Refresh request from [RFC5766], for as long as it wants that data connection to stay alive πŸ’–

when the client wants to end its relayed connection to the peer, it just closes the data connection to the server 🫢

Note: no mechanism for keeping NAT bindings alive is included here, potentially on the client data connection and on the peer data connection too. TURN-TCP doesn't provide that service. If that feature is deemed necessary, it can be built higher up the stack, in the application protocol being tunneled inside TURN-TCP. Also, TCP keep-alives MAY be used to keep the NAT bindings on the client data connection alive πŸ’…

5. TURN Server Behavior πŸ‘‘

5.1. Receiving a TCP Allocate Request πŸ¦‹

this is basically the same energy as [RFC5766], Section 6.2, just with a few plot twists 😭

  1. if REQUESTED-TRANSPORT is included and asks for a protocol other than UDP or TCP, the server MUST reject the request with a 442 (Unsupported Transport Protocol) error. if the value is UDP and local policy allows UDP, the server MUST carry on with the procedures of [RFC5766] instead of this document. if the value is UDP and local policy forbids it, the server MUST reject the request with a 403 (Forbidden) error.
  2. if the client connection transport is not TCP or TLS, the server MUST reject the request with a 400 (Bad Request) error.
  3. if the request contains DONT-FRAGMENT, EVEN-PORT, or RESERVATION-TOKEN, the server MUST reject the request with a 400 (Bad Request) error.
  4. a TCP relayed transport address MUST be allocated instead of a UDP one ✨
  5. the RESERVATION-TOKEN attribute MUST NOT be present in the success response πŸ™ˆ

if all the checks pass, the server MUST start accepting incoming TCP connections on the relayed transport address. peep Section 5.3 for the details πŸŽ€

5.2. Receiving a Connect Request πŸ”₯

okay so when the server gets a Connect request, here's the tea πŸ“

if the request arrives on a TCP connection with no allocation, the server MUST return a 437 (Allocation Mismatch) error.

if the server is already processing a Connect request for this allocation with the same XOR-PEER-ADDRESS, it MUST return a 446 (Connection Already Exists) error.

if the server has already processed a Connect request successfully for this allocation with the same XOR-PEER-ADDRESS, and the resulting client and peer data connections are pending or active, it MUST return a 446 (Connection Already Exists) error.

if the request doesn't contain an XOR-PEER-ADDRESS attribute, or that attribute is invalid, the server MUST return a 400 (Bad Request) error.

if the new connection is forbidden by local policy, the server MUST reject the request with a 403 (Forbidden) error.

otherwise, the server MUST initiate an outgoing TCP connection. the local endpoint is the relayed transport address tied to the allocation. the remote endpoint is whatever XOR-PEER-ADDRESS points to. if the connection attempt fails or times out, the server MUST return a 447 (Connection Timeout or Failure) error. the timeout value MUST be at least 30 seconds ⏰

if the connection succeeds, it's now called a peer data connection πŸ¦‹ the server MUST buffer any data received from the client. it also adjusts its advertised TCP receive window to match how much empty buffer space it has.

the server MUST include the CONNECTION-ID attribute in the Connect success response. the attribute's value MUST uniquely identify the peer data connection πŸͺͺ

if no ConnectionBind request tied to this peer data connection shows up after 30 seconds, the peer data connection MUST be closed. bye bye πŸ‘‹

5.3. Receiving a TCP Connection on a Relayed Transport Address 🌸

when a server gets an incoming TCP connection on a relayed transport address, here's what happens πŸ’œ

the server MUST accept the connection. if that isn't successful, nothing gets sent to the client over the control connection.

if the connection is accepted successfully, it's now called a peer data connection. the server MUST buffer any data received from the peer. it adjusts its advertised TCP receive window to reflect the empty buffer space too ✨

if no permission has been installed for this peer on this allocation, the server MUST close the connection with the peer immediately after accepting it πŸšͺ

otherwise, the server sends a ConnectionAttempt indication to the client over the control connection. the indication MUST include an XOR-PEER-ADDRESS attribute holding the peer's transport address, plus a CONNECTION-ID attribute that uniquely identifies the peer data connection πŸͺ„

if no ConnectionBind request tied to this peer data connection arrives after 30 seconds, the peer data connection MUST be closed πŸ’€

5.4. Receiving a ConnectionBind Request πŸ’«

when a server gets a ConnectionBind request, it goes like this 🧚

if the client connection transport is not TCP or TLS, the server MUST return a 400 (Bad Request) error.

if the request doesn't contain the CONNECTION-ID attribute, or that attribute doesn't point to an existing pending connection, the server MUST return a 400 (Bad Request) error.

otherwise, the client connection is now called a client data connection. data received on it MUST be sent as-is to the associated peer data connection.

data received on the associated peer data connection MUST be sent as-is on this client data connection. this includes data that arrived after the associated Connect request was processed successfully and before this ConnectionBind request came in. the vibes are immaculate 🌈

5.5. Data Connection Maintenance 🫧

if the allocation tied to a data connection expires, the data connection MUST be closed.

when a client data connection gets closed, the server MUST close the matching peer data connection.

when a peer data connection gets closed, the server MUST close the matching client data connection. one goes, they all go πŸ’…

6. IANA Considerations πŸ“‹

this spec defines a bunch of new STUN methods, STUN attributes, and STUN error codes. IANA added all of these new protocol elements to the Session Traversal Utilities for NAT (STUN) Parameters registry πŸ—‚οΈ

6.1. New STUN Methods 🌷

this section lists the codepoints for the new STUN methods defined here. check Sections 4 and 5 for what these methods actually do 🧠

0x000a :  Connect
0x000b :  ConnectionBind
0x000c :  ConnectionAttempt

6.2. New STUN Attributes πŸŽ€

this STUN extension defines the following new attribute:

0x002a :  CONNECTION-ID

6.2.1. CONNECTION-ID πŸͺͺ

the CONNECTION-ID attribute uniquely identifies a peer data connection. it's a 32-bit unsigned integral value πŸ”’

6.3. New STUN Error Codes 🚫

446    Connection Already Exists
447    Connection Timeout or Failure

7. Security Considerations 🚨

okay bestie, this part is SERIOUS 😭 after a TCP connection is set up between the server and a peer, and before a ConnectionBind request comes in from the client, the server buffers all the data it gets from the peer. this protocol lets the server drop the connection if the buffer is about to go past a limit set by local policy. that policy should make sure memory resources don't get exceeded. see also [RFC4732], Section 2.1.3 for more on this.

all the security considerations that apply to STUN [RFC5389] and TURN [RFC5766] apply to this document too. no skipping the homework πŸ“š

8. Acknowledgements 🫢

big thanks to Rohan Mahy and Philip Matthews for their early work getting this doc started πŸ’–

the authors also want to thank Alfred E. Heggestad, Ari Keranen, Marc Petit-Huguenin, Dave Thaler, and Dan Wing for their comments and suggestions. the squad πŸ‘‘

9. References πŸ“š

9.1. Normative References πŸ”’

[RFC2119]  Bradner, S., "Key words for use in RFCs to Indicate
           Requirement Levels", BCP 14, RFC 2119, March 1997.

[RFC5389]  Rosenberg, J., Mahy, R., Matthews, P., and D. Wing,
           "Session Traversal Utilities for NAT (STUN)", RFC 5389,
           October 2008.

[RFC5766]  Mahy, R., Matthews, P., and J. Rosenberg, "Traversal Using
           Relays around NAT (TURN): Relay Extensions to Session
           Traversal Utilities for NAT (STUN)", RFC 5766, April 2010.

9.2. Informative References πŸ“–

[RFC4732]  Handley, M., Rescorla, E., and IAB, "Internet Denial-of-
           Service Considerations", RFC 4732, December 2006.

[RFC5245]  Rosenberg, J., "Interactive Connectivity Establishment
           (ICE): A Protocol for Network Address Translator (NAT)
           Traversal for Offer/Answer Protocols", RFC 5245,
           April 2010.

Authors' Addresses πŸ’Œ

Simon Perreault (editor)
Viagenie
2875 boul. Laurier, suite D2-630
Quebec, QC  G1V 2M2
Canada

Phone: +1 418 656 9254
EMail: simon.perreault@viagenie.ca
URI:   http://www.viagenie.ca


Jonathan Rosenberg
jdrosen.net
Monmouth, NJ
US

EMail: jdrosen@jdrosen.net
URI:   http://www.jdrosen.net

that's a wrap on RFC 6062, bestie 🌈✨

πŸ“¦ where this page comes from