メインコンテンツまでスキップ

15. STUN Attributes (STUN属性)

STUNヘッダーの後には、0個以上の属性が続きます。各属性は、16ビットのタイプ、16ビットの長さ、および値を持つTLVエンコーディングでなければなりません(MUST)。各STUN属性は32ビット境界で終了しなければなりません(MUST)。前述のように、属性内のすべてのフィールドは最上位ビットを最初に送信します。

    0                   1                   2                   3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Type | Length |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Value (variable) ....
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

図4: STUN属性のフォーマット

長さフィールドの値は、パディング前の属性のValue部分の長さをバイト単位で含まなければなりません(MUST)。STUNは属性を32ビット境界に整列するため、コンテンツが4バイトの倍数でない属性は、値が4バイトの倍数を含むように1、2、または3バイトのパディングでパディングされます。パディングビットは無視され、任意の値にすることができます。

任意の属性タイプはSTUNメッセージに複数回出現してもかまいません(MAY)。特に指定がない限り、出現順序は重要です。受信者は最初の出現のみを処理する必要があり、受信者は重複を無視してもかまいません(MAY)。

必要に応じて本仕様の将来の改訂が新しい属性を追加できるようにするため、属性空間は2つの範囲に分割されています。0x0000から0x7FFFの値を持つ属性タイプは理解必須属性であり、これはSTUNエージェントが属性を理解しない限りメッセージを正常に処理できないことを意味します。0x8000から0xFFFFの値を持つ属性タイプは理解オプション属性であり、これはSTUNエージェントがそれらを理解しない場合に無視できることを意味します。

STUN属性タイプのセットはIANAによって維持されています。本仕様によって定義された初期セットはセクション18.2にあります。

このセクションの残りの部分では、本仕様で定義されているさまざまな属性のフォーマットについて説明します。

15.1. MAPPED-ADDRESS

MAPPED-ADDRESS属性は、クライアントの反射トランスポートアドレス (reflexive transport address) を示します。8ビットのアドレスファミリと16ビットのポートで構成され、その後にIPアドレスを表す固定長の値が続きます。アドレスファミリがIPv4の場合、アドレスは32ビットでなければなりません(MUST)。アドレスファミリがIPv6の場合、アドレスは128ビットでなければなりません(MUST)。すべてのフィールドはネットワークバイトオーダーでなければなりません。

MAPPED-ADDRESS属性のフォーマットは次のとおりです:

    0                   1                   2                   3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|0 0 0 0 0 0 0 0| Family | Port |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| |
| Address (32 bits or 128 bits) |
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

図5: MAPPED-ADDRESS属性のフォーマット

アドレスファミリは次の値を取ることができます:

  • 0x01: IPv4
  • 0x02: IPv6

MAPPED-ADDRESSの最初の8ビットは0に設定されなければならず(MUST)、受信者によって無視されなければなりません(MUST)。これらのビットは、自然な32ビット境界でパラメータを整列するために存在します。

この属性は、RFC 3489 [RFC3489]クライアントとの後方互換性を実現するためにサーバーによってのみ使用されます。

15.2. XOR-MAPPED-ADDRESS

XOR-MAPPED-ADDRESS属性は、MAPPED-ADDRESS属性と同一ですが、反射トランスポートアドレスがXOR関数によって難読化されている点が異なります。

XOR-MAPPED-ADDRESSのフォーマットは次のとおりです:

   0                   1                   2                   3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|x x x x x x x x| Family | X-Port |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| X-Address (Variable)
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

図6: XOR-MAPPED-ADDRESS属性のフォーマット

FamilyはIPアドレスファミリを表し、MAPPED-ADDRESSのFamilyと同じ方法でエンコードされます。

X-Portは、ホストバイトオーダーのマップされたポートを取得し、マジッククッキーの最上位16ビットとXORし、その結果をネットワークバイトオーダーに変換することによって計算されます。IPアドレスファミリがIPv4の場合、X-Addressは、ホストバイトオーダーのマップされたIPアドレスを取得し、マジッククッキーとXORし、結果をネットワークバイトオーダーに変換することによって計算されます。IPアドレスファミリがIPv6の場合、X-Addressは、ホストバイトオーダーのマップされたIPアドレスを取得し、マジッククッキーと96ビットトランザクションIDの連結とXORし、結果をネットワークバイトオーダーに変換することによって計算されます。

属性の値の最初の8ビットをエンコードおよび処理するための規則、属性の複数の出現を処理するための規則、およびアドレスファミリを処理するための規則は、MAPPED-ADDRESSと同じです。

: XOR-MAPPED-ADDRESSとMAPPED-ADDRESSは、トランスポートアドレスのエンコーディングのみが異なります。前者は、トランスポートアドレスをマジッククッキーと排他的論理和することによってエンコードします。後者は、それを直接バイナリ形式でエンコードします。RFC 3489は元々MAPPED-ADDRESSのみを指定していました。しかし、展開経験により、一部のNATがNATの公開IPアドレスを含む32ビットバイナリペイロード(STUNのMAPPED-ADDRESS属性など)を書き換えることがわかりました。これは善意ではあるが誤った一般的なALG機能を提供する試みです。このような動作はSTUNの動作を妨げ、STUNのメッセージ整合性チェックの失敗も引き起こします。

15.3. USERNAME

USERNAME属性はメッセージ整合性に使用されます。メッセージ整合性チェックで使用されるユーザー名とパスワードの組み合わせを識別します。

USERNAMEの値は可変長の値です。513バイト未満のUTF-8 [RFC3629]エンコードシーケンスを含まなければならず(MUST)、SASLprep [RFC4013]を使用して処理されている必要があります(MUST)。

15.4. MESSAGE-INTEGRITY

MESSAGE-INTEGRITY属性には、STUNメッセージのHMAC-SHA1 [RFC2104]が含まれます。MESSAGE-INTEGRITY属性は、任意のSTUNメッセージタイプに存在できます。SHA1ハッシュを使用するため、HMACは20バイトになります。HMACへの入力として使用されるテキストは、ヘッダーを含むSTUNメッセージで、MESSAGE-INTEGRITY属性の前の属性までを含みます。FINGERPRINT属性(MESSAGE-INTEGRITYの後に表示される)を除き、エージェントはMESSAGE-INTEGRITYの後に続くすべての他の属性を無視しなければなりません(MUST)。

HMACの鍵は、長期資格情報または短期資格情報が使用されているかどうかによって異なります。長期資格情報の場合、鍵は16バイトです:

key = MD5(username ":" realm ":" SASLprep(password))

つまり、16バイトの鍵は、次の5つのフィールドを連結した結果にMD5ハッシュを実行することによって形成されます:(1) ユーザー名(USERNAME属性から、引用符と末尾のnullを削除、この場合はすでにSASLprepが適用されている)、(2) 単一のコロン、(3) レルム(引用符と末尾のnullを削除)、(4) 単一のコロン、(5) パスワード(末尾のnullを削除し、SASLprepを使用して処理後)。たとえば、ユーザー名が'user'、レルムが'realm'、パスワードが'pass'の場合、16バイトのHMAC鍵は文字列'user:realm:pass'に対してMD5ハッシュを実行した結果となり、ハッシュは0x8493fbc53ba582fb4c044c456bdc40ebになります。

短期資格情報の場合:

key = SASLprep(password)

ここで、MD5はRFC 1321 [RFC1321]で定義され、SASLprep()はRFC 4013 [RFC4013]で定義されています。

長期資格情報と共に使用される場合の鍵の構造は、SIPも使用するシステムでの展開を容易にします。通常、SIPのダイジェスト認証メカニズムを使用するSIPシステムは、実際にはデータベースにパスワードを保存しません。代わりに、上記で定義された鍵と等しいH(A1)と呼ばれる値を保存します。

上記の規則に基づいて、MESSAGE-INTEGRITYを構築するために使用されるハッシュには、STUNメッセージヘッダーからの長さフィールドが含まれます。ハッシュを実行する前に、MESSAGE-INTEGRITY属性をメッセージに挿入する必要があります(MUST)(ダミーコンテンツを使用)。次に、長さをMESSAGE-INTEGRITY属性自体までを含むメッセージの長さを指すように設定する必要があります(MUST)が、その後の属性は除外します。計算が実行されると、MESSAGE-INTEGRITY属性の値を入力でき、STUNヘッダーの長さの値を正しい値(メッセージ全体の長さ)に設定できます。同様に、MESSAGE-INTEGRITYを検証する場合、HMACを計算する前に、長さフィールドをMESSAGE-INTEGRITY属性の終わりを指すように調整する必要があります。FINGERPRINT などの属性がMESSAGE-INTEGRITYの後に表示される場合、このような調整が必要です。

15.5. FINGERPRINT

FINGERPRINT属性は、すべてのSTUNメッセージに存在してもかまいません(MAY)。属性の値は、FINGERPRINT属性自体までの(ただし除外する)STUNメッセージのCRC-32として計算され、32ビット値0x5354554eとXORされます(XORは、アプリケーションパケットもその中でCRC-32を使用している場合に役立ちます)。32ビットCRCは、ITU V.42 [ITU.V42.2002]で定義されているもので、生成多項式x32+x26+x23+x22+x16+x12+x11+x10+x8+x7+x5+x4+x2+x+1を持ちます。存在する場合、FINGERPRINT属性はメッセージの最後の属性でなければならず(MUST)、したがってMESSAGE-INTEGRITYの後に表示されます。

FINGERPRINT属性は、STUNパケットを他のプロトコルのパケットと区別するのに役立ちます。セクション8を参照してください。

MESSAGE-INTEGRITYと同様に、FINGERPRINT属性で使用されるCRCは、STUNメッセージヘッダーからの長さフィールドをカバーします。したがって、この値は正しく、CRCの計算前にメッセージ長の一部としてCRC属性を含める必要があります。メッセージでFINGERPRINT属性を使用する場合、属性は最初にダミー値でメッセージに配置され、次にCRCが計算され、次に属性の値が更新されます。MESSAGE-INTEGRITY属性も存在する場合、CRCはMESSAGE-INTEGRITY属性の値もカバーするため、CRCが計算される前に正しいメッセージ整合性値を持つ必要があります。

15.6. ERROR-CODE

ERROR-CODE属性はエラー応答メッセージで使用されます。300から699の範囲の数値エラーコード値と、UTF-8 [RFC3629]でエンコードされたテキスト理由フレーズが含まれ、コード割り当てとセマンティクスにおいてSIP [RFC3261]およびHTTP [RFC2616]と一貫しています。理由フレーズはユーザー消費を目的としており、エラーコードに適した任意のものにすることができます。定義されたエラーコードの推奨理由フレーズは、エラーコードのIANAレジストリに含まれています。理由フレーズは、128文字未満のUTF-8 [RFC3629]エンコードシーケンスでなければなりません(MUST)(最大763バイト)。

    0                   1                   2                   3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Reserved, should be 0 |Class| Number |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Reason Phrase (variable) ..
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

図7: ERROR-CODE属性

処理を容易にするために、エラーコードのクラス(百の位)は、図7に示すように、コードの残りの部分と別にエンコードされます。

予約ビットは0であるべきであり(SHOULD)、32ビット境界での整列のためのものです。受信者はこれらのビットを無視しなければなりません(MUST)。Classはエラーコードの百の位を表します。値は3から6の間でなければなりません(MUST)。Numberはエラーコードのモジュロ100を表し、その値は0から99の間でなければなりません(MUST)。

推奨理由フレーズとともに、次のエラーコードが定義されています:

300 Try Alternate: クライアントはこのリクエストのために代替サーバーに連絡する必要があります。このエラー応答は、リクエストにUSERNAME属性と有効なMESSAGE-INTEGRITY属性が含まれている場合にのみ送信されなければなりません(MUST)。そうでない場合、送信してはならず(MUST NOT)、エラーコード400(Bad Request)が推奨されます。このエラー応答はMESSAGE-INTEGRITY属性で保護されなければならず(MUST)、受信者は代替サーバーにリダイレクトする前にこの応答のMESSAGE-INTEGRITYを検証しなければなりません(MUST)。

: 300応答のメッセージ整合性を生成および検証しないと、パス上の攻撃者が300応答を偽造し、後続のSTUNメッセージを被害者に送信させる可能性があります。

400 Bad Request: リクエストの形式が正しくありません。クライアントは、以前の試行から変更せずにリクエストを再試行すべきではありません(SHOULD NOT)。サーバーはこのエラーに対して有効なMESSAGE-INTEGRITYを生成できない可能性があるため、クライアントはこの応答で有効なMESSAGE-INTEGRITY属性を期待してはなりません(MUST NOT)。

401 Unauthorized: リクエストに続行するための正しい資格情報が含まれていませんでした。クライアントは適切な資格情報でリクエストを再試行する必要があります。

420 Unknown Attribute: サーバーが理解しない理解必須属性を含むSTUNパケットを受信しました。サーバーは、この未知の属性をエラー応答のUNKNOWN-ATTRIBUTE属性に入れなければなりません(MUST)。

438 Stale Nonce: クライアントによって使用されたNONCEが有効でなくなりました。クライアントは、応答で提供されたNONCEを使用して再試行する必要があります。

500 Server Error: サーバーで一時的なエラーが発生しました。クライアントは再試行する必要があります。

15.7. REALM

REALM属性は、リクエストとレスポンスに存在できます。RFC 3261 [RFC3261]で説明されている「realm-value」の文法を満たすテキストが含まれていますが、二重引用符とその周囲の空白はありません。つまり、引用符で囲まれていないrealm-value(したがってqdtextまたはquoted-pairのシーケンス)です。128文字未満のUTF-8 [RFC3629]エンコードシーケンスでなければならず(MUST)(最大763バイト)、SASLprep [RFC4013]を使用して処理されている必要があります(MUST)。

リクエストにREALM属性が存在することは、認証に長期資格情報が使用されていることを示します。特定のエラー応答での存在は、サーバーがクライアントに認証に長期資格情報を使用してほしいことを示します。

15.8. NONCE

NONCE属性は、リクエストとレスポンスに存在できます。RFC 3261 [RFC3261]で定義されているqdtextまたはquoted-pairのシーケンスが含まれます。これは、NONCE属性には実際の引用符文字が含まれないことを意味します。サーバーでのnonce値の選択に関するガイダンスについては、RFC 2617 [RFC2617]のセクション4.3を参照してください。

128文字未満でなければなりません(MUST)(最大763バイト)。

15.9. UNKNOWN-ATTRIBUTES

UNKNOWN-ATTRIBUTES属性は、ERROR-CODE属性の応答コードが420の場合にのみエラー応答に存在します。

この属性には、16ビット値のリストが含まれており、それぞれがサーバーによって理解されなかった属性タイプを表します。

    0                   1                   2                   3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Attribute 1 Type | Attribute 2 Type |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Attribute 3 Type | Attribute 4 Type ...
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

図8: UNKNOWN-ATTRIBUTES属性のフォーマット

: [RFC3489]では、このフィールドは最後の属性を複製することによって32にパディングされました。本仕様のこのバージョンでは、代わりに属性の通常のパディング規則が使用されます。

15.10. SOFTWARE

SOFTWARE属性には、メッセージを送信するエージェントが使用しているソフトウェアのテキスト記述が含まれます。クライアントとサーバーによって使用されます。その値には、製造元とバージョン番号を含めるべきです(SHOULD)。この属性はプロトコルの動作に影響を与えず、診断およびデバッグ目的のツールとしてのみ機能します。SOFTWAREの値は可変長です。128文字未満のUTF-8 [RFC3629]エンコードシーケンスでなければなりません(MUST)(最大763バイト)。

15.11. ALTERNATE-SERVER

代替サーバーは、STUNクライアントが試すべき別のSTUNサーバーを識別する代替トランスポートアドレスを表します。

MAPPED-ADDRESSと同じ方法でエンコードされるため、IPアドレスによって単一のサーバーを参照します。IPアドレスファミリは、リクエストのソースIPアドレスのアドレスファミリと同一でなければなりません(MUST)。