6. Création d'une allocation
Une allocation sur le serveur est créée à l'aide d'une transaction Allocate.
6.1. Envoi d'une demande Allocate
Le client forme une demande Allocate comme suit.
Le client choisit d'abord une adresse de transport hôte. Il est recommandé que le client choisisse une adresse de transport inutilisée, généralement en permettant au système d'exploitation sous-jacent de choisir un port inutilisé pour un nouveau socket.
Le client choisit ensuite un protocole de transport à utiliser entre le client et le serveur. Le protocole de transport doit être l'un des suivants : UDP, TCP ou TLS-over-TCP. Étant donné que cette spécification n'autorise que l'UDP entre le serveur et les pairs, il est recommandé que le client choisisse UDP sauf s'il a une raison d'utiliser un transport différent. Une raison de choisir un transport différent serait que le client pense (peut-être par configuration ou par expérimentation) qu'il est incapable de contacter un serveur TURN en utilisant UDP. Voir la section 2.1 pour plus de discussion.
Le client choisit également une adresse de transport de serveur, ce qui devrait être fait comme suit. Le client reçoit (peut-être par configuration) un nom de domaine pour un serveur TURN. Le client utilise ensuite les procédures DNS décrites dans [RFC5389], mais en utilisant un nom de service SRV de « turn » (ou « turns » pour TURN sur TLS) au lieu de « stun » (ou « stuns »). Par exemple, pour trouver des serveurs dans le domaine example.com, le client effectue une recherche pour '_turn._udp.example.com', '_turn._tcp.example.com' et '_turns._tcp.example.com' si le client souhaite communiquer avec le serveur en utilisant UDP, TCP ou TLS-over-TCP, respectivement.
Le client doit inclure un attribut REQUESTED-TRANSPORT dans la demande. Cet attribut spécifie le protocole de transport entre le serveur et les pairs (notez que ce n'est pas le protocole de transport qui apparaît dans le 5-tuple). Dans cette spécification, le type REQUESTED-TRANSPORT est toujours UDP. Cet attribut est inclus pour permettre aux extensions futures de spécifier d'autres protocoles.
Si le client souhaite que le serveur initialise le champ temps avant expiration de l'allocation à une valeur autre que la durée de vie par défaut, il peut inclure un attribut LIFETIME spécifiant sa valeur souhaitée. Il ne s'agit que d'une demande, et le serveur peut choisir d'utiliser une valeur différente. Notez que le serveur ignorera les demandes d'initialisation du champ à une valeur inférieure à la valeur par défaut.
Si le client souhaite utiliser ultérieurement l'attribut DONT-FRAGMENT dans une ou plusieurs indications Send sur cette allocation, alors le client devrait inclure l'attribut DONT-FRAGMENT dans la demande Allocate. Cela permet au client de tester si le serveur prend en charge cet attribut.
Si le client exige que le numéro de port de l'adresse de transport relayée soit pair, le client inclut l'attribut EVEN-PORT. Si cet attribut n'est pas inclus, alors le port peut être pair ou impair. En définissant le bit R dans l'attribut EVEN-PORT à 1, le client peut demander que le serveur réserve le numéro de port suivant le plus élevé (sur la même adresse IP) pour une allocation ultérieure. Si le bit R est à 0, aucune telle demande n'est faite.
Le client peut également inclure un attribut RESERVATION-TOKEN dans la demande pour demander au serveur d'utiliser un port précédemment réservé pour l'allocation. Si l'attribut RESERVATION-TOKEN est inclus, alors le client doit omettre l'attribut EVEN-PORT.
Une fois construite, le client envoie la demande Allocate sur le 5-tuple.
6.2. Réception d'une demande Allocate
Lorsque le serveur reçoit une demande Allocate, il effectue les vérifications suivantes :
-
Le serveur doit exiger que la demande soit authentifiée. Cette authentification doit être effectuée en utilisant le mécanisme de credential à long terme de [RFC5389] à moins que le client et le serveur n'acceptent d'utiliser un autre mécanisme par le biais d'une procédure en dehors du cadre de ce document.
-
Le serveur vérifie si le 5-tuple est actuellement utilisé par une allocation existante. Si oui, le serveur rejette la demande avec une erreur 437 (Allocation Mismatch).
-
Le serveur vérifie si la demande contient un attribut REQUESTED-TRANSPORT. Si l'attribut REQUESTED-TRANSPORT n'est pas inclus ou est mal formé, le serveur rejette la demande avec une erreur 400 (Bad Request). Sinon, si l'attribut est inclus mais spécifie un protocole autre que UDP, le serveur rejette la demande avec une erreur 442 (Unsupported Transport Protocol).
-
La demande peut contenir un attribut DONT-FRAGMENT. Si c'est le cas, mais que le serveur ne prend pas en charge l'envoi de datagrammes UDP avec le bit DF défini à 1 (voir section 12), alors le serveur traite l'attribut DONT-FRAGMENT dans la demande Allocate comme un attribut de compréhension requis inconnu.
-
Le serveur vérifie si la demande contient un attribut RESERVATION-TOKEN. Si oui, et que la demande contient également un attribut EVEN-PORT, alors le serveur rejette la demande avec une erreur 400 (Bad Request). Sinon, il vérifie si le token est valide (c'est-à-dire que le token est dans la plage et n'a pas expiré et que l'adresse de transport relayée correspondante est toujours disponible). Si le token n'est pas valide pour une raison quelconque, le serveur rejette la demande avec une erreur 508 (Insufficient Capacity).
-
Le serveur vérifie si la demande contient un attribut EVEN-PORT. Si oui, alors le serveur vérifie qu'il peut satisfaire la demande (c'est-à-dire qu'il peut allouer une adresse de transport relayée comme décrit ci-dessous). Si le serveur ne peut pas satisfaire la demande, alors le serveur rejette la demande avec une erreur 508 (Insufficient Capacity).
-
À tout moment, le serveur peut choisir de rejeter la demande avec une erreur 486 (Allocation Quota Reached) s'il estime que le client tente de dépasser un quota d'allocation défini localement. Le serveur est libre de définir ce quota d'allocation de la manière qu'il souhaite, mais devrait le définir en fonction du nom d'utilisateur utilisé pour authentifier la demande, et non sur l'adresse de transport du client.
-
Également à tout moment, le serveur peut choisir de rejeter la demande avec une erreur 300 (Try Alternate) s'il souhaite rediriger le client vers un serveur différent. L'utilisation de ce code d'erreur et de cet attribut suit la spécification dans [RFC5389].
Si toutes les vérifications réussissent, le serveur crée l'allocation. Le 5-tuple est défini sur le 5-tuple de la demande Allocate, tandis que la liste des permissions et la liste des canaux sont initialement vides.
Le serveur choisit une adresse de transport relayée pour l'allocation comme suit :
-
Si la demande contient un RESERVATION-TOKEN, le serveur utilise l'adresse de transport précédemment réservée correspondant au token inclus (si elle est toujours disponible). Notez que la réservation est une réservation à l'échelle du serveur et n'est pas spécifique à une allocation particulière, car la demande Allocate contenant le RESERVATION-TOKEN utilise un 5-tuple différent de la demande Allocate qui a effectué la réservation. Le 5-tuple pour la demande Allocate contenant l'attribut RESERVATION-TOKEN peut être n'importe quel 5-tuple autorisé ; il peut utiliser une adresse IP et un port client différents, un protocole de transport différent, et même une adresse IP et un port serveur différents (à condition que l'adresse IP et le port du serveur soient ceux sur lesquels le serveur écoute les demandes TURN).
-
Si la demande contient un attribut EVEN-PORT avec le bit R défini à 0, alors le serveur alloue une adresse de transport relayée avec un numéro de port pair.
-
Si la demande contient un attribut EVEN-PORT avec le bit R défini à 1, alors le serveur recherche une paire de numéros de port N et N+1 sur la même adresse IP, où N est pair. Le port N est utilisé dans l'allocation actuelle, tandis que l'adresse de transport relayée avec le port N+1 se voit attribuer un token et est réservée pour une allocation future. Le serveur doit maintenir cette réservation pendant au moins 30 secondes, et peut choisir de la maintenir plus longtemps (par exemple, jusqu'à ce que l'allocation avec le port N expire). Le serveur inclut ensuite le token dans un attribut RESERVATION-TOKEN dans la réponse de succès.
-
Sinon, le serveur alloue toute adresse de transport relayée disponible.
Dans tous les cas, le serveur devrait uniquement allouer des ports de la plage 49152 - 65535 (la plage de ports dynamiques et/ou privés [Port-Numbers]), à moins que l'application serveur TURN ne sache, par un moyen non spécifié ici, que d'autres applications exécutées sur le même hôte que l'application serveur TURN ne seront pas affectées par l'allocation de ports en dehors de cette plage. Cette condition peut souvent être satisfaite en exécutant l'application serveur TURN sur une machine dédiée et/ou en organisant que toute autre application sur la machine alloue des ports avant le démarrage de l'application serveur TURN. Dans tous les cas, le serveur TURN ne devrait pas allouer de ports dans la plage 0 - 1023 (la plage de ports bien connus) pour décourager les clients d'utiliser TURN pour exécuter des services standard.
NOTE : L'IETF enquête actuellement sur le sujet des attributions de ports aléatoires pour éviter certains types d'attaques (voir [TSVWG-PORT]). Il est fortement encouragé que les implémenteurs TURN se tiennent au courant de ce sujet et, le cas échéant, implémentent un algorithme d'attribution de ports aléatoires. Ceci est particulièrement applicable aux serveurs qui choisissent de pré-allouer un certain nombre de ports du système d'exploitation sous-jacent et de les attribuer ensuite aux allocations ; par exemple, un serveur peut choisir cette technique pour implémenter l'attribut EVEN-PORT.
Le serveur détermine la valeur initiale du champ temps avant expiration comme suit. Si la demande contient un attribut LIFETIME, alors le serveur calcule le minimum de la durée de vie proposée par le client et de la durée de vie maximale autorisée du serveur. Si cette valeur calculée est supérieure à la durée de vie par défaut, alors le serveur utilise la durée de vie calculée comme valeur initiale du champ temps avant expiration. Sinon, le serveur utilise la durée de vie par défaut. Il est recommandé que le serveur utilise une valeur de durée de vie maximale autorisée ne dépassant pas 3600 secondes (1 heure). Les serveurs qui implémentent des quotas d'allocation ou facturent les utilisateurs pour les allocations d'une manière ou d'une autre peuvent souhaiter utiliser une durée de vie maximale autorisée plus petite (peut-être aussi petite que la durée de vie par défaut) pour supprimer plus rapidement les allocations orphelines (c'est-à-dire les allocations où le client correspondant a planté ou s'est terminé ou la connexion client a été perdue pour une raison quelconque). Notez également que le temps avant expiration est recalculé avec chaque demande Refresh réussie, et donc la valeur calculée ici s'applique uniquement jusqu'au premier rafraîchissement.
Une fois l'allocation créée, le serveur répond avec une réponse de succès. La réponse de succès contient :
-
Un attribut XOR-RELAYED-ADDRESS contenant l'adresse de transport relayée.
-
Un attribut LIFETIME contenant la valeur actuelle du minuteur temps avant expiration.
-
Un attribut RESERVATION-TOKEN (si une deuxième adresse de transport relayée a été réservée).
-
Un attribut XOR-MAPPED-ADDRESS contenant l'adresse IP et le port du client (du 5-tuple).
NOTE : L'attribut XOR-MAPPED-ADDRESS est inclus dans la réponse pour la commodité du client. TURN lui-même ne fait pas usage de cette valeur, mais les clients exécutant ICE ont généralement besoin de cette valeur et peuvent ainsi éviter de devoir effectuer une transaction Binding supplémentaire avec un serveur STUN pour l'obtenir.
La réponse (succès ou erreur) est renvoyée au client sur le 5-tuple.
NOTE : Lorsque la demande Allocate est envoyée via UDP, la section 7.3.1 de [RFC5389] exige que le serveur gère les éventuelles retransmissions de la demande afin que les retransmissions n'entraînent pas la création de plusieurs allocations. Les implémentations peuvent y parvenir en utilisant l'approche dite « pile sans état » comme suit. Pour détecter les retransmissions lorsqu'une demande originale a réussi à créer une allocation, le serveur peut stocker l'ID de transaction utilisé dans la demande de création avec les données d'allocation et le comparer avec les demandes Allocate entrantes sur le même 5-tuple. Une fois qu'une telle demande est détectée, le serveur peut arrêter l'analyse de la demande et générer immédiatement une réponse de succès. Lors de la construction de cette réponse, la valeur de l'attribut LIFETIME peut être tirée du champ temps avant expiration dans les données d'état d'allocation, même si cette valeur peut différer légèrement de la valeur LIFETIME initialement retournée. De plus, le serveur peut avoir besoin de stocker une indication de tout token de réservation retourné dans la réponse originale afin que celui-ci puisse être retourné dans toutes les réponses retransmises.
Pour le cas où la demande originale n'a pas réussi à créer une allocation, le serveur peut choisir de ne rien faire de spécial. Notez cependant qu'il existe un cas rare où le serveur rejette la demande originale mais accepte la demande retransmise (car les conditions ont changé dans la brève période intermédiaire). Si le client reçoit la première réponse (rejet), il ignorera la deuxième réponse (succès) et croira qu'une allocation n'a pas été créée. Une allocation créée de cette manière finira par expirer, car le client ne la rafraîchira pas. De plus, si le client réessaie plus tard avec le même 5-tuple mais un ID de transaction différent, il recevra une erreur 437 (Allocation Mismatch), ce qui l'amènera à réessayer avec un 5-tuple différent. Le serveur peut minimiser la durée de vie des allocations « orphelines » de cette manière en utilisant une valeur de durée de vie maximale plus petite.
6.3. Réception d'une réponse de succès Allocate
Si le client reçoit une réponse de succès Allocate, alors il doit vérifier que l'adresse mappée et l'adresse de transport relayée sont toutes deux dans la famille d'adresses que le client comprend et est prêt à gérer. Cette spécification ne couvre que le cas où les deux adresses sont des adresses IPv4. Si l'une ou l'autre adresse n'est pas dans une famille d'adresses que le client est prêt à gérer, alors le client doit supprimer l'allocation (section 7), et ne doit pas tenter de créer une autre allocation sur ce serveur jusqu'à ce qu'il croie que l'incompatibilité a été corrigée.
L'IETF envisage actuellement des mécanismes de transition entre IPv4 et IPv6 qui pourraient entraîner qu'un client lance une demande Allocate via IPv6, mais la demande arriverait au serveur via IPv4, ou vice-versa.
Sinon, le client crée sa propre copie de la structure de données d'allocation pour suivre ce qui se passe sur le serveur. En particulier, le client doit se souvenir de la durée de vie réelle reçue du serveur, plutôt que de la valeur envoyée au serveur dans la demande. Le client doit également se souvenir du 5-tuple utilisé pour la demande et du nom d'utilisateur et du mot de passe qu'il a utilisés pour authentifier la demande afin de s'assurer qu'il les réutilise pour les messages ultérieurs. Le client doit également suivre les canaux et les permissions qu'il établit sur le serveur.
Le client souhaitera probablement envoyer l'adresse de transport relayée aux pairs (en utilisant une méthode non spécifiée ici) afin que les pairs puissent communiquer avec lui. Le client peut également souhaiter utiliser l'adresse réfléchie par le serveur qu'il reçoit dans l'attribut XOR-MAPPED-ADDRESS dans son traitement ICE.
6.4. Réception d'une réponse d'erreur Allocate
Si le client reçoit une réponse d'erreur Allocate, alors le traitement dépend du code d'erreur réel retourné :
-
(Demande expirée, Request Timed Out) : Il y a soit un problème avec le serveur, soit un problème pour atteindre le serveur avec le transport choisi. Le client considère la transaction actuelle comme ayant échoué mais peut choisir de réessayer la demande Allocate en utilisant un transport différent (par exemple, TCP au lieu d'UDP).
-
300 (Try Alternate) : Le serveur souhaite que le client utilise le serveur spécifié dans l'attribut ALTERNATE-SERVER à la place. Le client considère la transaction actuelle comme ayant échoué, mais devrait essayer une demande Allocate avec le serveur alternatif avant d'essayer d'autres serveurs (par exemple, d'autres serveurs découverts en utilisant les procédures SRV). Lorsqu'il essaie la demande Allocate avec le serveur alternatif, le client suit les procédures ALTERNATE-SERVER spécifiées dans [RFC5389].
-
400 (Bad Request) : Le serveur estime que la demande du client est mal formée pour une raison quelconque. Le client considère la transaction actuelle comme ayant échoué. Le client peut notifier l'utilisateur ou l'opérateur et ne devrait pas réessayer la demande avec ce serveur jusqu'à ce qu'il croie que le problème a été résolu.
-
401 (Unauthorized) : Si le client a suivi les procédures du mécanisme de credential à long terme et reçoit toujours cette erreur, alors le serveur n'accepte pas les credentials du client. Dans ce cas, le client considère la transaction actuelle comme ayant échoué et devrait notifier l'utilisateur ou l'opérateur. Le client ne devrait pas envoyer d'autres demandes à ce serveur jusqu'à ce qu'il croie que le problème a été résolu.
-
403 (Forbidden) : La demande est valide, mais le serveur refuse de l'exécuter, probablement en raison de restrictions administratives. Le client considère la transaction actuelle comme ayant échoué. Le client peut notifier l'utilisateur ou l'opérateur et ne devrait pas réessayer la même demande avec ce serveur jusqu'à ce qu'il croie que le problème a été résolu.
-
420 (Unknown Attribute) : Si le client a inclus un attribut DONT-FRAGMENT dans la demande et que le serveur a rejeté la demande avec un code d'erreur 420 et a listé l'attribut DONT-FRAGMENT dans l'attribut UNKNOWN-ATTRIBUTES de la réponse d'erreur, alors le client sait maintenant que le serveur ne prend pas en charge l'attribut DONT-FRAGMENT. Le client considère la transaction actuelle comme ayant échoué mais peut choisir de réessayer la demande Allocate sans l'attribut DONT-FRAGMENT.
-
437 (Allocation Mismatch) : Cela indique que le client a choisi un 5-tuple que le serveur considère comme déjà utilisé. Une façon dont cela peut se produire est si un NAT intermédiaire a attribué une adresse de transport mappée qui a été utilisée par un autre client qui a récemment planté. Le client considère la transaction actuelle comme ayant échoué. Le client devrait choisir une autre adresse de transport client et réessayer la demande Allocate (avec un ID de transaction différent). Le client devrait essayer trois adresses de transport client différentes avant d'abandonner ce serveur. Une fois que le client abandonne le serveur, il ne devrait pas essayer de créer une autre allocation sur le serveur pendant 2 minutes.
-
438 (Stale Nonce) : Voir les procédures pour le mécanisme de credential à long terme [RFC5389].
-
441 (Wrong Credentials) : Le client ne devrait pas recevoir cette erreur en réponse à une demande Allocate. Le client peut notifier l'utilisateur ou l'opérateur et ne devrait pas réessayer la même demande avec ce serveur jusqu'à ce qu'il croie que le problème a été résolu.
-
442 (Unsupported Transport Address) : Le client ne devrait pas recevoir cette erreur en réponse à une demande d'allocation UDP. Le client peut notifier l'utilisateur ou l'opérateur et ne devrait pas retenter la demande avec ce serveur jusqu'à ce qu'il croie que le problème a été résolu.
-
486 (Allocation Quota Reached) : Le serveur est actuellement incapable de créer d'autres allocations avec ce nom d'utilisateur. Le client considère la transaction actuelle comme ayant échoué. Le client devrait attendre au moins 1 minute avant d'essayer de créer d'autres allocations sur le serveur.
-
508 (Insufficient Capacity) : Le serveur n'a plus d'adresses de transport relayées disponibles, ou n'en a aucune avec les propriétés demandées, ou celle qui correspond au token de réservation spécifié n'est pas disponible. Le client considère l'opération actuelle comme ayant échoué. Si le client utilise l'attribut EVEN-PORT ou RESERVATION-TOKEN, alors le client peut choisir de supprimer ou de modifier cet attribut et d'essayer à nouveau immédiatement. Sinon, le client devrait attendre au moins 1 minute avant d'essayer de créer d'autres allocations sur ce serveur.
Une réponse d'erreur inconnue doit être traitée comme décrit dans [RFC5389].