16. Exemple détaillé (Detailed Example)
Cette section fournit un exemple d'utilisation de TURN, montrant en détail le contenu des messages échangés. L'exemple utilise le diagramme réseau montré dans la vue d'ensemble (Figure 1).
Pour chaque message, les attributs contenus dans le message et leurs valeurs sont affichés. Pour plus de commodité, les valeurs sont affichées dans un format lisible par l'homme plutôt que de montrer les octets réels ; par exemple, "XOR-RELAYED-ADDRESS=192.0.2.15:9000" indique qu'un attribut XOR-RELAYED-ADDRESS est présent avec une adresse de 192.0.2.15 et un port de 9000, où l'adresse et le port sont affichés avant que l'opération XOR n'ait été appliquée. Pour les attributs avec des valeurs de type chaîne (par exemple, SOFTWARE="Example client, version 1.03" et NONCE="adl7W7PeDU4hKE72jdaQvbAMcr6h39sm"), la valeur de l'attribut est affichée entre guillemets pour la lisibilité, mais ces guillemets n'apparaissent pas dans la valeur réelle.
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=... | | |
Le client sélectionne d'abord une adresse de transport hôte à utiliser pour la session TURN. Dans cet exemple, le client a sélectionné 10.1.1.2:49721 comme indiqué dans la Figure 1. Le client envoie ensuite une requête Allocate au serveur à l'adresse de transport du serveur. Le client a sélectionné aléatoirement un ID de transaction de 96 bits 0xA56250D3F17ABE679422DE85 pour cette transaction, qui est encodé dans le champ ID de transaction dans l'en-tête fixe. Le client inclut un attribut SOFTWARE fournissant des informations sur le logiciel client, ici la valeur est "Example client, version 1.03", indiquant qu'il s'agit de la version 1.03 de quelque chose appelé le client Example. Le client inclut un attribut LIFETIME car il souhaite que l'allocation ait une durée de vie plus longue que la valeur par défaut de 10 minutes ; la valeur de cet attribut est de 3600 secondes, correspondant à 1 heure. Le client doit toujours inclure un attribut REQUESTED-TRANSPORT dans une requête Allocate ; la seule valeur autorisée par cette spécification est 17, qui indique le transport UDP entre le serveur et les pairs. Le client inclut également un attribut DONT-FRAGMENT car il souhaite utiliser l'attribut DONT-FRAGMENT dans les indications Send plus tard ; cet attribut se compose uniquement de l'en-tête d'attribut, il n'y a pas de partie valeur. Enfin, nous supposons que le client n'a pas récemment interagi avec le serveur, et n'inclut donc pas d'attribut USERNAME, REALM, NONCE ou MESSAGE-INTEGRITY. Notez que l'ordre des attributs dans le message est arbitraire (sauf pour les attributs MESSAGE-INTEGRITY et FINGERPRINT), et le client aurait pu utiliser un ordre différent.
Le serveur exige que toutes les requêtes soient authentifiées. Ainsi, lorsque le serveur reçoit la requête Allocate initiale, il rejette la requête car celle-ci ne contient pas les attributs d'authentification. Suivant les procédures du mécanisme d'identification à long terme STUN [RFC5389], le serveur inclut un attribut ERROR-CODE avec une valeur de 401 (Unauthorized, Non autorisé), un attribut REALM qui spécifie le domaine d'authentification utilisé par le serveur (ici, le domaine du serveur "example.com"), et une valeur nonce dans l'attribut NONCE. Le serveur inclut également un attribut SOFTWARE, fournissant des informations sur le logiciel du serveur.
Après avoir reçu l'erreur 401, le client retente la requête Allocate, cette fois en incluant les attributs d'authentification. Le client a sélectionné un nouvel ID de transaction et remplit la nouvelle requête Allocate avec les mêmes attributs qu'auparavant. Le client inclut un attribut USERNAME ; il utilise la valeur de domaine reçue du serveur pour l'aider à déterminer quelle valeur utiliser, ici le client est configuré pour utiliser le nom d'utilisateur "George" pour le domaine "example.com". Le client inclut un attribut REALM et un attribut NONCE, copiés de la réponse d'erreur 401. Enfin, le client inclut un attribut MESSAGE-INTEGRITY comme dernier attribut dans le message ; la valeur de cet attribut est un hachage HMAC-SHA1 sur le contenu du message (affiché ci-dessus comme juste "...") ; ce calcul HMAC-SHA1 inclut une valeur de mot de passe. Ainsi, un attaquant ne peut pas calculer la valeur d'intégrité du message sans connaître le mot de passe secret.
Après avoir reçu la requête Allocate authentifiée, le serveur vérifie que tout est correct, puis crée une allocation. Le serveur répond avec une réponse de succès Allocate. Le serveur inclut un attribut LIFETIME donnant la durée de vie de l'allocation ; ici, le serveur a réduit la durée de vie d'1 heure demandée par le client à seulement 20 minutes, car ce serveur particulier n'autorise pas de durées de vie supérieures à 20 minutes. Le serveur inclut un attribut XOR-RELAYED-ADDRESS dont la valeur est l'adresse de transport relayée de l'allocation. Le serveur inclut un attribut XOR-MAPPED-ADDRESS dont la valeur est l'adresse réflexive du serveur du client ; cette valeur n'est pas utilisée ailleurs dans TURN, mais est retournée par commodité pour le client. Le serveur inclut un attribut MESSAGE-INTEGRITY pour authentifier la réponse et assurer son intégrité. Notez que la réponse n'inclut pas d'attribut USERNAME, REALM et NONCE. Le serveur inclut également un attribut SOFTWARE.
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=... | | |
Le client crée ensuite une permission pour le pair A en préparation de l'envoi de données d'application. Ceci est fait via une requête CreatePermission. L'attribut XOR-PEER-ADDRESS contient l'adresse IP pour laquelle une permission est établie (l'adresse IP du pair A). Notez que lorsqu'il est utilisé dans les requêtes CreatePermission, le numéro de port dans l'attribut est ignoré ; ici, il a été défini à zéro. Notez également comment le client utilise l'adresse IP réflexive du serveur du pair A plutôt que son adresse hôte (privée). Le client réutilise les valeurs de nom d'utilisateur, de domaine et de nonce de sa dernière requête sur l'allocation. Bien que cela soit autorisé, le client a choisi de ne pas inclure l'attribut SOFTWARE dans cette requête.
Le serveur reçoit la requête CreatePermission, crée la permission correspondante et répond avec une réponse de succès CreatePermission. Comme le client, le serveur a choisi de ne pas inclure l'attribut SOFTWARE dans sa réponse. Notez une fois de plus comment la réponse de succès contient un attribut MESSAGE-INTEGRITY (en supposant que le serveur utilise le mécanisme d'identification à long terme), mais pas d'attribut USERNAME, REALM et NONCE.
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=... | | |
Le client envoie maintenant des données d'application au pair A en utilisant une indication Send. L'adresse de transport réflexive du serveur du pair A est spécifiée dans l'attribut XOR-PEER-ADDRESS, et les données d'application sont spécifiées dans l'attribut DATA (affiché ci-dessus comme juste "..."). Le client effectue une forme de découverte de MTU de chemin au niveau de la couche application, et spécifie donc (en incluant l'attribut DONT-FRAGMENT) que le serveur doit définir le bit DF dans le datagramme UDP à envoyer au pair. Il n'est pas possible d'authentifier les indications en utilisant le mécanisme d'identification à long terme de STUN, il n'y a donc pas d'attribut MESSAGE-INTEGRITY dans le message. Une application souhaitant s'assurer que ses données ne sont pas altérées ou usurpées doit protéger l'intégrité de ses données au niveau de l'application.
Après avoir reçu l'indication Send, le serveur extrait les données d'application et les envoie dans un datagramme UDP au pair A, avec l'adresse de transport relayée comme source du datagramme, et avec le bit DF défini comme demandé. Notez que si le client n'avait pas précédemment établi une permission pour l'adresse IP réflexive du serveur du pair A, le serveur aurait silencieusement ignoré l'indication Send.
Le pair A répond ensuite avec son propre datagramme UDP contenant des données d'application. Le datagramme est envoyé à l'adresse de transport relayée sur le serveur. Lorsque cela arrive, le serveur crée une indication Data, inclut la source du datagramme UDP dans l'attribut XOR-PEER-ADDRESS et les données du datagramme UDP dans l'attribut DATA. L'indication Data résultante est ensuite envoyée au client.
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=... | | |
Le client lie maintenant un canal au pair B, spécifiant un numéro de canal inutilisé (0x4000) dans l'attribut CHANNEL-NUMBER et l'adresse de transport du pair B dans l'attribut XOR-PEER-ADDRESS. Comme auparavant, le client réutilise le nom d'utilisateur, le domaine et le nonce de sa dernière requête.
Après réception de la requête, le serveur lie le numéro de canal au pair et installe une permission pour l'adresse IP du pair B, puis répond avec une réponse de succès ChannelBind.
TURN TURN Peer Peer
client server A B
|--- ChannelData ------------------->| | |
| Channel-number=0x4000 |--- UDP datagram --------->|
| Data=... | Data=... |
| | | |
| |<-- UDP datagram ----------|
| | Data=... | |
|<-- ChannelData --------------------| | |
| Channel-number=0x4000 | | |
| Data=... | | |
Le client envoie maintenant un message ChannelData au serveur avec des données destinées au pair B. Un message ChannelData n'est pas un message STUN et n'a donc pas d'ID de transaction ; au lieu de cela, il n'a que trois champs : le numéro de canal, les données et la longueur des données. Ici, le champ de numéro de canal est 0x4000 (le canal que le client vient de lier au pair B). Lorsque le serveur reçoit le message ChannelData, il vérifie que le canal est actuellement lié (il l'est), puis transmet les données au pair B dans un datagramme UDP, en utilisant l'adresse de transport relayée comme adresse de transport source et 192.0.2.210:49191 (la valeur de l'attribut XOR-PEER-ADDRESS dans la requête ChannelBind) comme adresse de transport de destination.
Plus tard, le pair B envoie un datagramme UDP à l'adresse de transport relayée. Cela provoque l'envoi par le serveur d'un message ChannelData au client contenant les données du datagramme UDP. Le serveur sait à quel client envoyer le message ChannelData en raison de l'adresse de transport relayée à laquelle le datagramme UDP a été envoyé, et sait utiliser le canal 0x4000 car c'est le canal lié à 192.0.2.210:49191. Notez que s'il n'y avait pas de numéro de canal lié à cette adresse, le serveur aurait utilisé une indication Data.
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) | | |
Quelque temps avant l'expiration de la durée de vie de 20 minutes, le client rafraîchit l'allocation. Ceci est fait en utilisant une requête Refresh. Comme auparavant, le client inclut les dernières valeurs de nom d'utilisateur, de domaine et de nonce dans la requête. Le client inclut également un attribut SOFTWARE, suivant la recommandation d'inclure toujours cet attribut dans les messages Allocate et Refresh. Lorsque le serveur reçoit la requête Refresh, il remarque que le nonce est devenu obsolète et répond donc avec une erreur 438 (Stale Nonce, Nonce obsolète), fournissant une nouvelle valeur de nonce. Le client retente alors la requête, cette fois avec la nouvelle valeur de nonce. Cette deuxième tentative est acceptée et le serveur répond avec une réponse de succès. Notez que le client n'a pas inclus d'attribut LIFETIME dans la requête, donc le serveur a rafraîchi l'allocation pour la durée de vie par défaut de 10 minutes (comme indiqué dans l'attribut LIFETIME dans la réponse de succès).