6. Creating an Allocation (アロケーションの作成)
サーバー上のアロケーションは、Allocateトランザクションを使用して作成されます。
6.1. Sending an Allocate Request (Allocateリクエストの送信)
クライアントは、以下のようにAllocateリクエストを構成します。
クライアントは、まずホストトランスポートアドレスを選択します。クライアントは、通常、基盤となるOSが新しいソケット用に未使用のポートを選択できるようにすることで、未使用のトランスポートアドレスを選択することが推奨されます (RECOMMENDED)。
次に、クライアントは、クライアントとサーバー間で使用するトランスポートプロトコルを選択します。トランスポートプロトコルは、UDP、TCP、またはTLS-over-TCPのいずれかでなければなりません (MUST)。本仕様では、サーバーとピア間でUDPのみが許可されているため、異なるトランスポートを使用する理由がない限り、クライアントはUDPを選択することが推奨されます (RECOMMENDED)。異なるトランスポートを選択する理由の1つは、クライアントが(設定または実験を通じて)UDPを使用してTURNサーバーに接続できないと考えている場合です。詳細については、セクション2.1を参照してください。
クライアントはまた、サーバートランスポートアドレスを選択します。これは以下のように行うべきです (SHOULD)。クライアントは(おそらく設定を通じて)TURNサーバーのドメイン名を受け取ります。次に、クライアントは [RFC5389] で説明されているDNS手順を使用しますが、「stun」(または「stuns」)の代わりに「turn」(またはTLS over TURNの場合は「turns」)のSRVサービス名を使用します。たとえば、example.comドメイン内のサーバーを検索するために、クライアントがUDP、TCP、またはTLS-over-TCPを使用してサーバーと通信したい場合、クライアントはそれぞれ '_turn._udp.example.com'、'_turn._tcp.example.com'、'_turns._tcp.example.com' のルックアップを実行します。
クライアントは、リクエストにREQUESTED-TRANSPORT属性を含めなければなりません (MUST)。この属性は、サーバーとピア間のトランスポートプロトコルを指定します(これは5タプルに現れるトランスポートプロトコルではないことに注意してください)。本仕様では、REQUESTED-TRANSPORTタイプは常にUDPです。この属性は、将来の拡張が他のプロトコルを指定できるようにするために含まれています。
クライアントが、サーバーにアロケーションの有効期限フィールドをデフォルトの有効期間以外の値に初期化してほしい場合、希望する値を指定するLIFETIME属性を含めてもよいです (MAY)。これは単なるリクエストであり、サーバーは異なる値を使用することを選択できます。サーバーは、フィールドをデフォルト値未満に初期化するリクエストを無視することに注意してください。
クライアントが、このアロケーション上の1つ以上のSendインディケーションで後でDONT-FRAGMENT属性を使用したい場合、クライアントはAllocateリクエストにDONT-FRAGMENT属性を含めるべきです (SHOULD)。これにより、クライアントはサーバーがこの属性をサポートしているかどうかをテストできます。
クライアントが中継トランスポートアドレスのポート番号が偶数であることを要求する場合、クライアントはEVEN-PORT属性を含めます。この属性が含まれていない場合、ポートは偶数または奇数になります。EVEN-PORT属性のRビットを1に設定することで、クライアントは、サーバーが後続のアロケーションのために次に高いポート番号(同じIPアドレス上)を予約することを要求できます。Rビットが0の場合、そのようなリクエストは行われません。
クライアントは、サーバーに以前に予約されたポートをアロケーションに使用するよう要求するために、リクエストにRESERVATION-TOKEN属性を含めてもよいです (MAY)。RESERVATION-TOKEN属性が含まれている場合、クライアントはEVEN-PORT属性を省略しなければなりません (MUST)。
構築が完了したら、クライアントは5タプル上でAllocateリクエストを送信します。
6.2. Receiving an Allocate Request (Allocateリクエストの受信)
サーバーがAllocateリクエストを受信すると、以下のチェックを実行します:
-
サーバーは、リクエストが認証されることを要求しなければなりません (MUST)。この認証は、クライアントとサーバーが本文書の範囲外の何らかの手順を通じて別のメカニズムを使用することに同意しない限り、[RFC5389] の長期クレデンシャルメカニズムを使用して行われなければなりません (MUST)。
-
サーバーは、5タプルが既存のアロケーションによって現在使用されているかどうかをチェックします。使用されている場合、サーバーは437 (Allocation Mismatch) エラーでリクエストを拒否します。
-
サーバーは、リクエストにREQUESTED-TRANSPORT属性が含まれているかどうかをチェックします。REQUESTED-TRANSPORT属性が含まれていない、または不正な形式の場合、サーバーは400 (Bad Request) エラーでリクエストを拒否します。それ以外の場合、属性が含まれているがUDP以外のプロトコルを指定している場合、サーバーは442 (Unsupported Transport Protocol) エラーでリクエストを拒否します。
-
リクエストにはDONT-FRAGMENT属性が含まれている場合があります。含まれているが、サーバーがDFビットを1に設定したUDPデータグラムの送信をサポートしていない場合(セクション12を参照)、サーバーはAllocateリクエスト内のDONT-FRAGMENT属性を未知の必須理解属性 (Unknown Comprehension-Required Attribute) として扱います。
-
サーバーは、リクエストにRESERVATION-TOKEN属性が含まれているかどうかをチェックします。含まれており、リクエストにEVEN-PORT属性も含まれている場合、サーバーは400 (Bad Request) エラーでリクエストを拒否します。それ以外の場合、トークンが有効かどうか(つまり、トークンが範囲内にあり、期限切れではなく、対応する中継トランスポートアドレスがまだ利用可能である)をチェックします。何らかの理由でトークンが無効な場合、サーバーは508 (Insufficient Capacity) エラーでリクエストを拒否します。
-
サーバーは、リクエストにEVEN-PORT属性が含まれているかどうかをチェックします。含まれている場合、サーバーはリクエストを満たすことができるかどうか(つまり、以下に説明するように中継トランスポートアドレスを割り当てることができるか)をチェックします。サーバーがリクエストを満たすことができない場合、サーバーは508 (Insufficient Capacity) エラーでリクエストを拒否します。
-
いつでも、サーバーは、クライアントがローカルに定義された何らかのアロケーションクォータを超えようとしていると感じた場合、486 (Allocation Quota Reached) エラーでリクエストを拒否することを選択してもよいです (MAY)。サーバーは、このアロケーションクォータを任意の方法で自由に定義できますが、クライアントのトランスポートアドレスではなく、リクエストの認証に使用されたユーザー名に基づいて定義すべきです (SHOULD)。
-
また、いつでも、サーバーは、クライアントを別のサーバーにリダイレクトしたい場合、300 (Try Alternate) エラーでリクエストを拒否することを選択してもよいです (MAY)。このエラーコードと属性の使用は、[RFC5389] の仕様に従います。
すべてのチェックに合格した場合、サーバーはアロケーションを作成します。5タプルはAllocateリクエストの5タプルに設定され、パーミッションリストとチャネルリストは最初は空です。
サーバーは、以下のようにアロケーション用の中継トランスポートアドレスを選択します:
-
リクエストにRESERVATION-TOKENが含まれている場合、サーバーは、含まれているトークンに対応する以前に予約されたトランスポートアドレス(まだ利用可能な場合)を使用します。予約はサーバー全体の予約であり、特定のアロケーションに固有ではないことに注意してください。これは、RESERVATION-TOKENを含むAllocateリクエストが、予約を行ったAllocateリクエストとは異なる5タプルを使用するためです。RESERVATION-TOKEN属性を含むAllocateリクエストの5タプルは、任意の許可された5タプルにすることができます。異なるクライアントIPアドレスとポート、異なるトランスポートプロトコル、さらには異なるサーバーIPアドレスとポートを使用できます(もちろん、サーバーIPアドレスとポートがサーバーがTURNリクエストをリッスンしているアドレスとポートである場合)。
-
リクエストにRビットが0に設定されたEVEN-PORT属性が含まれている場合、サーバーは偶数のポート番号を持つ中継トランスポートアドレスを割り当てます。
-
リクエストにRビットが1に設定されたEVEN-PORT属性が含まれている場合、サーバーは同じIPアドレス上でポート番号NとN+1のペアを探します。ここで、Nは偶数です。ポートNは現在のアロケーションに使用され、ポートN+1を持つ中継トランスポートアドレスにはトークンが割り当てられ、将来のアロケーション用に予約されます。サーバーは、この予約を少なくとも30秒間保持しなければならず (MUST)、より長く保持することを選択してもよいです (MAY)(たとえば、ポートNを持つアロケーションが期限切れになるまで)。次に、サーバーは成功応答のRESERVATION-TOKEN属性にトークンを含めます。
-
それ以外の場合、サーバーは利用可能な任意の中継トランスポートアドレスを割り当てます。
すべての場合において、サーバーは、TURNサーバーアプリケーションが、ここで指定されていない何らかの手段を通じて、TURNサーバーアプリケーションと同じホスト上で実行されている他のアプリケーションがこの範囲外のポートを割り当てることによって影響を受けないことを知っている場合を除き、範囲49152〜65535(動的および/またはプライベートポート範囲 [Port-Numbers])からのみポートを割り当てるべきです (SHOULD)。この条件は、多くの場合、専用マシン上でTURNサーバーアプリケーションを実行すること、および/またはマシン上の他のアプリケーションがTURNサーバーアプリケーションが起動する前にポートを割り当てるように手配することで満たすことができます。いずれの場合も、TURNサーバーは、クライアントがTURNを使用して標準サービスを実行することを阻止するために、範囲0〜1023(Well-Knownポート範囲)からポートを割り当てるべきではありません (SHOULD NOT)。
注意: IETFは現在、特定の種類の攻撃を回避するためのランダム化されたポート割り当てのトピックを調査しています([TSVWG-PORT] を参照)。TURN実装者は、このトピックに注意を払い、適切な場合はランダム化されたポート割り当てアルゴリズムを実装することを強く推奨します。これは特に、基盤となるOSから多数のポートを事前に割り当て、後でそれらをアロケーションに割り当てることを選択するサーバーに適用されます。たとえば、サーバーはEVEN-PORT属性を実装するためにこの技術を選択する場合があります。
サーバーは、以下のように有効期限フィールドの初期値を決定します。リクエストにLIFETIME属性が含まれている場合、サーバーは、クライアントが提案した有効期間とサーバーの最大許可有効期間の最小値を計算します。この計算値がデフォルトの有効期間より大きい場合、サーバーは計算された有効期間を有効期限フィールドの初期値として使用します。それ以外の場合、サーバーはデフォルトの有効期間を使用します。サーバーは、3600秒(1時間)以下の最大許可有効期間値を使用することが推奨されます (RECOMMENDED)。アロケーションクォータを実装するか、何らかの方法でユーザーにアロケーションの料金を請求するサーバーは、孤立したアロケーション(つまり、対応するクライアントがクラッシュまたは終了したか、何らかの理由でクライアント接続が失われたアロケーション)をより迅速に削除するために、より小さい最大許可有効期間(おそらくデフォルトの有効期間と同じくらい小さい)を使用したい場合があります。また、有効期限は成功したRefreshリクエストごとに再計算されるため、ここで計算された値は最初の更新までのみ適用されることに注意してください。
アロケーションが作成されると、サーバーは成功応答で応答します。成功応答には以下が含まれます:
-
中継トランスポートアドレスを含むXOR-RELAYED-ADDRESS属性。
-
有効期限タイマーの現在の値を含むLIFETIME属性。
-
RESERVATION-TOKEN属性(2番目の中継トランスポートアドレスが予約された場合)。
-
クライアントのIPアドレスとポート(5タプルから)を含むXOR-MAPPED-ADDRESS属性。
注意: XOR-MAPPED-ADDRESS属性は、クライアントの便宜のために応答に含まれています。TURN自体はこの値を使用しませんが、ICEを実行しているクライアントは通常この値を必要とするため、STUNサーバーとの追加のBindingトランザクションを行う必要がなくなります。
応答(成功またはエラー)は、5タプル上でクライアントに送り返されます。
注意: AllocateリクエストがUDPで送信される場合、[RFC5389] のセクション7.3.1は、再送信によって複数のアロケーションが作成されないように、サーバーがリクエストの再送信の可能性を処理することを要求しています。実装は、いわゆる「ステートレススタックアプローチ」を使用してこれを実現できます。元のリクエストがアロケーションの作成に成功した場合の再送信を検出するために、サーバーは作成リクエストで使用されたトランザクションIDをアロケーションデータとともに保存し、同じ5タプル上の着信Allocateリクエストと比較できます。そのようなリクエストが検出されると、サーバーはリクエストの解析を停止し、すぐに成功応答を生成できます。この応答を構築する際、LIFETIME属性の値は、この値が元々返されたLIFETIME値とわずかに異なる場合でも、アロケーション状態データの有効期限フィールドから取得できます。さらに、サーバーは、元の応答で返された予約トークンの指示を保存する必要がある場合があります。これにより、再送信された応答で返すことができます。
元のリクエストがアロケーションの作成に失敗した場合、サーバーは特別なことを何もしないことを選択できます。ただし、サーバーが元のリクエストを拒否したが、再送信されたリクエストを受け入れる(短い間隔で条件が変わったため)というまれなケースがあることに注意してください。クライアントが最初の(拒否)応答を受信した場合、2番目の(成功)応答を無視し、アロケーションが作成されなかったと考えます。この方法で作成されたアロケーションは、クライアントが更新しないため、最終的にタイムアウトします。さらに、クライアントが後で同じ5タプルだが異なるトランザクションIDで再試行する場合、437 (Allocation Mismatch) を受信し、異なる5タプルで再試行します。サーバーは、より小さい最大有効期間値を使用することで、この方法で「孤立した」アロケーションの有効期間を最小化できます。
6.3. Receiving an Allocate Success Response (Allocate成功応答の受信)
クライアントがAllocate成功応答を受信した場合、マップされたアドレスと中継トランスポートアドレスの両方が、クライアントが理解し、処理する準備ができているアドレスファミリー内にあるかどうかをチェックしなければなりません (MUST)。本仕様は、両方のアドレスがIPv4アドレスである場合のみをカバーしています。いずれかのアドレスがクライアントが処理する準備ができているアドレスファミリー内にない場合、クライアントはアロケーションを削除しなければならず (MUST)(セクション7)、不一致が修正されたと考えるまで、そのサーバー上で別のアロケーションを作成しようとしてはなりません (MUST NOT)。
IETFは現在、IPv4とIPv6間の移行のためのメカニズムを検討しており、これによりクライアントがIPv6経由でAllocateリクエストを開始するが、リクエストはIPv4経由でサーバーに到着する、またはその逆の場合が生じる可能性があります。
それ以外の場合、クライアントは、サーバー上で何が起こっているかを追跡するために、アロケーションデータ構造の独自のコピーを作成します。特に、クライアントは、リクエストでサーバーに送信した値ではなく、サーバーから受け取った実際の有効期間を記憶する必要があります。クライアントはまた、リクエストに使用した5タプルと、リクエストの認証に使用したユーザー名とパスワードを記憶して、後続のメッセージで再利用できるようにしなければなりません。クライアントはまた、サーバー上で確立したチャネルとパーミッションを追跡する必要があります。
クライアントは、ピアが通信できるように、中継トランスポートアドレスをピアに送信したい場合があります(ここで指定されていない何らかの方法を使用)。クライアントはまた、XOR-MAPPED-ADDRESS属性で受信したサーバー反射アドレスをICE処理で使用したい場合があります。
6.4. Receiving an Allocate Error Response (Allocateエラー応答の受信)
クライアントがAllocateエラー応答を受信した場合、処理は返された実際のエラーコードによって異なります:
-
(リクエストタイムアウト、Request Timed Out): サーバーに問題があるか、選択したトランスポートを使用してサーバーに到達する際に問題があります。クライアントは現在のトランザクションを失敗したと見なしますが、異なるトランスポート(たとえば、UDPの代わりにTCP)を使用してAllocateリクエストを再試行することを選択してもよいです (MAY)。
-
300(Try Alternate): サーバーは、クライアントにALTERNATE-SERVER属性で指定されたサーバーを代わりに使用してほしいと考えています。クライアントは現在のトランザクションを失敗したと見なしますが、他のサーバー(たとえば、SRV手順を使用して発見された他のサーバー)を試す前に、代替サーバーでAllocateリクエストを試すべきです (SHOULD)。代替サーバーでAllocateリクエストを試す際、クライアントは [RFC5389] で指定されたALTERNATE-SERVER手順に従います。
-
400(Bad Request): サーバーは、クライアントのリクエストが何らかの理由で不正な形式であると考えています。クライアントは現在のトランザクションを失敗したと見なします。クライアントはユーザーまたはオペレーターに通知してもよく (MAY)、問題が修正されたと考えるまで、このサーバーでリクエストを再試行すべきではありません (SHOULD NOT)。
-
401(Unauthorized): クライアントが長期クレデンシャルメカニズムの手順に従ってもこのエラーが発生する場合、サーバーはクライアントのクレデンシャルを受け入れていません。この場合、クライアントは現在のトランザクションを失敗したと見なし、ユーザーまたはオペレーターに通知すべきです (SHOULD)。クライアントは、問題が修正されたと考えるまで、このサーバーにさらなるリクエストを送信すべきではありません (SHOULD NOT)。
-
403(Forbidden): リクエストは有効ですが、サーバーはおそらく管理上の制限のためにそれを実行することを拒否しています。クライアントは現在のトランザクションを失敗したと見なします。クライアントはユーザーまたはオペレーターに通知してもよく (MAY)、問題が修正されたと考えるまで、このサーバーで同じリクエストを再試行すべきではありません (SHOULD NOT)。
-
420(Unknown Attribute): クライアントがリクエストにDONT-FRAGMENT属性を含め、サーバーが420エラーコードでリクエストを拒否し、エラー応答のUNKNOWN-ATTRIBUTES属性にDONT-FRAGMENT属性をリストした場合、クライアントはサーバーがDONT-FRAGMENT属性をサポートしていないことを認識します。クライアントは現在のトランザクションを失敗したと見なしますが、DONT-FRAGMENT属性なしでAllocateリクエストを再試行することを選択してもよいです (MAY)。
-
437(Allocation Mismatch): これは、クライアントがサーバーが既に使用中と見なす5タプルを選択したことを示します。これが発生する1つの方法は、介在するNATが、最近クラッシュした別のクライアントによって使用されたマップされたトランスポートアドレスを割り当てた場合です。クライアントは現在のトランザクションを失敗したと見なします。クライアントは別のクライアントトランスポートアドレスを選択し、Allocateリクエストを再試行すべきです (SHOULD)(異なるトランザクションIDを使用)。クライアントは、このサーバーを諦める前に、3つの異なるクライアントトランスポートアドレスを試すべきです (SHOULD)。クライアントがサーバーを諦めたら、2分間はサーバー上で別のアロケーションを作成しようとすべきではありません (SHOULD NOT)。
-
438(Stale Nonce): 長期クレデンシャルメカニズム [RFC5389] の手順を参照してください。
-
441(Wrong Credentials): クライアントは、Allocateリクエストへの応答としてこのエラーを受信すべきではありません。クライアントはユーザーまたはオペレーターに通知してもよく (MAY)、問題が修正されたと考えるまで、このサーバーで同じリクエストを再試行すべきではありません (SHOULD NOT)。
-
442(Unsupported Transport Address): クライアントは、UDP割り当てリクエストへの応答としてこのエラーを受信すべきではありません。クライアントはユーザーまたはオペレーターに通知してもよく (MAY)、問題が修正されたと考えるまで、このサーバーでリクエストを再試行すべきではありません (SHOULD NOT)。
-
486(Allocation Quota Reached): サーバーは現在、このユーザー名でこれ以上のアロケーションを作成できません。クライアントは現在のトランザクションを失敗したと見なします。クライアントは、サーバー上でさらにアロケーションを作成しようとする前に、少なくとも1分間待つべきです (SHOULD)。
-
508(Insufficient Capacity): サーバーには利用可能な中継トランスポートアドレスがもうないか、要求されたプロパティを持つアドレスがないか、指定された予約トークンに対応するアドレスが利用できません。クライアントは現在の操作を失敗したと見なします。クライアントがEVEN-PORTまたはRESERVATION-TOKEN属性を使用している場合、クライアントはこの属性を削除または変更し、すぐに再試行することを選択してもよいです (MAY)。それ以外の場合、クライアントは、このサーバー上でさらにアロケーションを作成しようとする前に、少なくとも1分間待つべきです (SHOULD)。
未知のエラー応答は、[RFC5389] で説明されているように処理されなければなりません (MUST)。