Skip to main content

16. Detailed Example

This section gives an example of the use of TURN, showing in detail the contents of the messages exchanged. The example uses the network diagram shown in the Overview (Figure 1).

For each message, the attributes contained in the message and their values are shown. For convenience, values are shown in a human-readable format rather than showing the actual octets; for example, "XOR-RELAYED-ADDRESS=192.0.2.15:9000" indicates that a XOR-RELAYED-ADDRESS attribute is present with an address of 192.0.2.15 and a port of 9000, where the address and port are shown before the XOR operation has been applied. For attributes with string-like values (e.g., SOFTWARE="Example client, version 1.03" and NONCE="adl7W7PeDU4hKE72jdaQvbAMcr6h39sm"), the value of the attribute is shown in quotes for readability, but these quotes do not appear in the actual value.

 TURN                                 TURN           Peer          Peer
client server A B
| | | |
|--- Allocate request -------------->| | |
| Transaction-Id=0xA56250D3F17ABE679422DE85 | |
| SOFTWARE="Example client, version 1.03" | |
| LIFETIME=3600 (1 hour) | | |
| REQUESTED-TRANSPORT=17 (UDP) | | |
| DONT-FRAGMENT | | |
| | | |
|<-- Allocate error response --------| | |
| Transaction-Id=0xA56250D3F17ABE679422DE85 | |
| SOFTWARE="Example server, version 1.17" | |
| ERROR-CODE=401 (Unauthorized) | | |
| REALM="example.com" | | |
| NONCE="adl7W7PeDU4hKE72jdaQvbAMcr6h39sm" | |
| | | |
|--- Allocate request -------------->| | |
| Transaction-Id=0xC271E932AD7446A32C234492 | |
| SOFTWARE="Example client 1.03" | | |
| LIFETIME=3600 (1 hour) | | |
| REQUESTED-TRANSPORT=17 (UDP) | | |
| DONT-FRAGMENT | | |
| USERNAME="George" | | |
| REALM="example.com" | | |
| NONCE="adl7W7PeDU4hKE72jdaQvbAMcr6h39sm" | |
| MESSAGE-INTEGRITY=... | | |
| | | |
|<-- Allocate success response ------| | |
| Transaction-Id=0xC271E932AD7446A32C234492 | |
| SOFTWARE="Example server, version 1.17" | |
| LIFETIME=1200 (20 minutes) | | |
| XOR-RELAYED-ADDRESS=192.0.2.15:50000 | |
| XOR-MAPPED-ADDRESS=192.0.2.1:7000 | |
| MESSAGE-INTEGRITY=... | | |

The client first selects a host transport address to use for the TURN session. In this example, the client has selected 10.1.1.2:49721 as shown in Figure 1. The client then sends an Allocate request to the server at the server transport address. The client has randomly selected a 96-bit transaction id of 0xA56250D3F17ABE679422DE85 for this transaction, which is encoded in the transaction id field in the fixed header. The client includes a SOFTWARE attribute giving information about the client software, here the value is "Example client, version 1.03", indicating that this is version 1.03 of something called the Example client. The client includes a LIFETIME attribute because it wishes the allocation to have a longer lifetime than the default of 10 minutes; the value of this attribute is 3600 seconds, corresponding to 1 hour. The client must always include a REQUESTED-TRANSPORT attribute in an Allocate request; the only value allowed by this specification is 17, which indicates UDP transport between the server and the peers. The client also includes a DONT-FRAGMENT attribute because it wishes to use the DONT-FRAGMENT attribute in Send indications later on; this attribute consists of just the attribute header, there is no value part. Finally, we assume that the client has not recently interacted with the server, and thus does not include a USERNAME, REALM, NONCE, or MESSAGE-INTEGRITY attribute. Note that the order of the attributes in the message is arbitrary (except for the MESSAGE-INTEGRITY and FINGERPRINT attributes), and the client could have used a different order.

The server requires all requests to be authenticated. Thus, when the server receives the initial Allocate request, it rejects the request because the request does not contain the authentication attributes. Following the procedures of the STUN [RFC5389] long-term credential mechanism, the server includes an ERROR-CODE attribute with a value of 401 (Unauthorized), a REALM attribute that specifies the authentication realm used by the server (here, the server's domain "example.com"), and a nonce value in the NONCE attribute. The server also includes a SOFTWARE attribute, giving information about the server's software.

Upon receiving the 401 error, the client re-attempts the Allocate request, this time including the authentication attributes. The client has selected a new transaction id and fills in the new Allocate request with the same attributes as before. The client includes a USERNAME attribute; it uses the realm value received from the server to help it determine which value to use, here the client is configured to use the username "George" for the realm "example.com". The client includes a REALM and a NONCE attribute, copied from the 401 error response. Finally, the client includes a MESSAGE-INTEGRITY attribute as the last attribute in the message; the value of this attribute is an HMAC-SHA1 hash over the message contents (shown above as just "..."); this HMAC-SHA1 computation includes a password value. Thus, an attacker cannot compute the message integrity value without knowing the secret password.

Upon receiving the authenticated Allocate request, the server checks that everything is okay, then creates an allocation. The server replies with an Allocate success response. The server includes a LIFETIME attribute giving the lifetime of the allocation; here, the server has reduced the 1-hour lifetime requested by the client to only 20 minutes, as this particular server does not allow lifetimes longer than 20 minutes. The server includes an XOR-RELAYED-ADDRESS attribute whose value is the relayed transport address of the allocation. The server includes an XOR-MAPPED-ADDRESS attribute whose value is the server-reflexive address of the client; this value is not used elsewhere in TURN, but is returned as a convenience to the client. The server includes a MESSAGE-INTEGRITY attribute to authenticate the response and assure its integrity. Note that the response does not include a USERNAME, REALM, and NONCE attribute. The server also includes a SOFTWARE attribute.

 TURN                                 TURN           Peer          Peer
client server A B
|--- CreatePermission request ------>| | |
| Transaction-Id=0xE5913A8F460956CA277D3319 | |
| XOR-PEER-ADDRESS=192.0.2.150:0 | | |
| USERNAME="George" | | |
| REALM="example.com" | | |
| NONCE="adl7W7PeDU4hKE72jdaQvbAMcr6h39sm" | |
| MESSAGE-INTEGRITY=... | | |
| | | |
|<-- CreatePermission success resp.--| | |
| Transaction-Id=0xE5913A8F460956CA277D3319 | |
| MESSAGE-INTEGRITY=... | | |

The client then creates a permission for peer A in preparation for sending it some application data. This is done through a CreatePermission request. The XOR-PEER-ADDRESS attribute contains the IP address for which a permission is established (the IP address of peer A). Note that when used in CreatePermission requests, the port number in the attribute is ignored; here, it has been set to zero. Also note how the client uses the server-reflexive IP address of peer A rather than its (private) host address. The client re-uses the username, realm, and nonce values from its last request on the allocation. Though this is allowed, the client has chosen not to include the SOFTWARE attribute in this request.

The server receives the CreatePermission request, creates the corresponding permission, and replies with a CreatePermission success response. Like the client, the server has chosen not to include the SOFTWARE attribute in its reply. Note once again how the success response contains a MESSAGE-INTEGRITY attribute (assuming the server uses the long-term credential mechanism), but not a USERNAME, REALM, and NONCE attribute.

 TURN                                 TURN           Peer          Peer
client server A B
|--- Send indication --------------->| | |
| Transaction-Id=0x1278E9ACA2711637EF7D3328 | |
| XOR-PEER-ADDRESS=192.0.2.150:32102 | |
| DONT-FRAGMENT | | |
| DATA=... | | |
| |-- UDP dgm ->| |
| | data=... | |
| | | |
| |<- UDP dgm --| |
| | data=... | |
|<-- Data indication ----------------| | |
| Transaction-Id=0x8231AE8F9242DA9FF287FEFF | |
| XOR-PEER-ADDRESS=192.0.2.150:32102 | |
| DATA=... | | |

The client now sends some application data to peer A using a Send indication. The server-reflexive transport address of peer A is specified in the XOR-PEER-ADDRESS attribute, and the application data is specified in the DATA attribute (shown above as just "..."). The client is doing some form of path MTU discovery at the application layer, and so specifies (by including the DONT-FRAGMENT attribute) that the server should set the DF bit in the UDP datagram to send to the peer. It is not possible to authenticate indications using the long-term credential mechanism of STUN, thus there is no MESSAGE-INTEGRITY attribute in the message. An application wishing to ensure that its data is not being tampered with or spoofed must integrity protect its data at the application level.

Upon receiving the Send indication, the server extracts the application data and sends it in a UDP datagram to peer A, with the relayed transport address as the source of the datagram, and with the DF bit set as requested. Note that had the client not previously established a permission for the server-reflexive IP address of peer A, the server would have silently discarded the Send indication.

Peer A then replies with its own UDP datagram containing application data. The datagram is sent to the relayed transport address on the server. When this arrives, the server creates a Data indication,包含 UDP 数据报的源在 XOR-PEER-ADDRESS 属性中,UDP 数据报的数据在 DATA 属性中。然后将生成的 Data 指示发送到客户端。

 TURN                                 TURN           Peer          Peer
client server A B
|--- ChannelBind request ----------->| | |
| Transaction-Id=0x6490D3BC175AFF3D84513212 | |
| CHANNEL-NUMBER=0x4000 | | |
| XOR-PEER-ADDRESS=192.0.2.210:49191 | |
| USERNAME="George" | | |
| REALM="example.com" | | |
| NONCE="adl7W7PeDU4hKE72jdaQvbAMcr6h39sm" | |
| MESSAGE-INTEGRITY=... | | |
| | | |
|<-- ChannelBind success response ---| | |
| Transaction-Id=0x6490D3BC175AFF3D84513212 | |
| MESSAGE-INTEGRITY=... | | |

The client now binds a channel to peer B, specifying an unused channel number (0x4000) in the CHANNEL-NUMBER attribute and the transport address of peer B in the XOR-PEER-ADDRESS attribute. As before, the client re-uses the username, realm, and nonce from its last request.

Upon receipt of the request, the server binds the channel number to the peer and installs a permission for the IP address of peer B, then replies with a ChannelBind success response.

 TURN                                 TURN           Peer          Peer
client server A B
|--- ChannelData ------------------->| | |
| Channel-number=0x4000 |--- UDP datagram --------->|
| Data=... | Data=... |
| | | |
| |<-- UDP datagram ----------|
| | Data=... | |
|<-- ChannelData --------------------| | |
| Channel-number=0x4000 | | |
| Data=... | | |

The client now sends a ChannelData message to the server with data destined for peer B. A ChannelData message is not a STUN message and thus has no transaction id; instead, it has only three fields: the channel number, the data, and the data length. Here, the channel number field is 0x4000 (the channel the client just bound to peer B). When the server receives the ChannelData message, it checks that the channel is currently bound (it is), then forwards the data to peer B in a UDP datagram, using the relayed transport address as the source transport address and 192.0.2.210:49191 (the value of the XOR-PEER-ADDRESS attribute in the ChannelBind request) as the destination transport address.

Later, peer B sends a UDP datagram to the relayed transport address. This causes the server to send a ChannelData message to the client containing the data from the UDP datagram. The server knows which client to send the ChannelData message to because of the relayed transport address to which the UDP datagram was sent, and knows to use channel 0x4000 because that is the channel bound to 192.0.2.210:49191. Note that if there was not a channel number bound to that address, the server would have used a Data indication.

 TURN                                 TURN           Peer          Peer
client server A B
|--- Refresh request --------------->| | |
| Transaction-Id=0x0864B3C27ADE9354B4312414 | |
| SOFTWARE="Example client 1.03" | | |
| USERNAME="George" | | |
| REALM="example.com" | | |
| NONCE="adl7W7PeDU4hKE72jdaQvbAMcr6h39sm" | |
| MESSAGE-INTEGRITY=... | | |
| | | |
|<-- Refresh error response ---------| | |
| Transaction-Id=0x0864B3C27ADE9354B4312414 | |
| SOFTWARE="Example server, version 1.17" | |
| ERROR-CODE=438 (Stale Nonce) | | |
| REALM="example.com" | | |
| NONCE="npSw1Xw239bBwGYhjNWgz2yH47sxB2j" | |
| | | |
|--- Refresh request --------------->| | |
| Transaction-Id=0x427BD3E625A85FC731DC4191 | |
| SOFTWARE="Example client 1.03" | | |
| USERNAME="George" | | |
| REALM="example.com" | | |
| NONCE="npSw1Xw239bBwGYhjNWgz2yH47sxB2j" | |
| MESSAGE-INTEGRITY=... | | |
| | | |
|<-- Refresh success response -------| | |
| Transaction-Id=0x427BD3E625A85FC731DC4191 | |
| SOFTWARE="Example server, version 1.17" | |
| LIFETIME=600 (10 minutes) | | |

Sometime before the 20-minute lifetime is up, the client refreshes the allocation. This is done using a Refresh request. As before, the client includes the latest username, realm, and nonce values in the request. The client also includes a SOFTWARE attribute, following the recommendation to always include this attribute in Allocate and Refresh messages. When the server receives the Refresh request, it notices that the nonce has gone stale and so replies with a 438 (Stale Nonce) error, supplying a new nonce value. The client then re-attempts the request, this time with the new nonce value. This second attempt is accepted and the server replies with a success response. Note that the client did not include a LIFETIME attribute in the request, so the server refreshed the allocation for the default lifetime of 10 minutes (as shown in the LIFETIME attribute in the success response).