2014年1月18日土曜日

P2P探訪 STUNでNat越え その4



まずは、スーパーノード候補として最有力なNATであるか調査してみましょう。
外部から見えている、「アドレスとポート」が常に一定であり。
他からのアクセスを制限していないNATのことです。(フルコーン)


○STUNでの確認方法

 どのようにして、制限があるかを確認するのでしょうか? STUNの仕組みはとても単純です。実際に通信してみて各種条件で通信ができるか試します。実際に試してみて、もしも通信できたならば、同一の条件下の端末とは通信可能といえるでしょう。


具体的には、実際に外部からメッセージを送信してもらう。そして、送信しもらったメッセージを受け取る事ができるかを確認します。

  • 接続したUDPサーバーから、メッセージを受け取れる事
  • 接続したUDPサーバーの異なるポートから、メッセージを受け取れること
  • 接続したUDPサーバーと異なるサーバーから、メッセージを受け取る事ができる事



○Bindingリクエスト

 実際にSTUNの通信内容を見ていきましょう。サーバーにレスポンスする条件(ポートとアドレス)を指定してレスポンスを返しもらいます。このレスポンスの依頼をSTUNでは、Bindingリクエストと読んでいます。

 例えば以下のような、依頼を出す事でしょう。
  1. CL はサーバーへ「受け取ったサーバーから、レスポンスを返してもらう。」依頼をだす。
  2. CL はサーバーへ「受け取ったサーバーから、ポートだけ変えてレスポンスを返してもらう。」依頼をだす。
  3. CL はサーバーへ「受け取ったサーバーから、ポートとアドレスを変えてレスポンスを返してもらう。」依頼をだす。


 3のレスポンスを受け取る事ができたならば、「フルコーン」といえます。



○ 実際に送受信するメッセージ

STUNではBindingリクエストと呼ばれるリクエストほをサーバーへサーバーへ送信します。


1. 送信先のアドレスとポートから返信するように依頼をだす。
{
0x00, 0x00,   // 最初の2byteは0
0x00, 0x01,   // Binding リクエストを意味する 0x01 
0x00, 0x08,   // Attrinuteのサイズ 8バイトを表す 0x08
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, // 16バイトのid
0x00, 0x03, // ChangeRequest 
0x00, 0x04, // attibuteのボティのサイズ 4
0x00, 0x00, 0x00, 0x00// 送信先のアドレスとポートから返信する
};

2. IPとポートを変えて返信

{
0x00, 0x00,   // 最初の2byteは0
0x00, 0x01,   // Binding リクエストを意味する 0x01 
0x00, 0x08,   // Attrinuteのサイズ 8バイトを表す 0x08
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, // 16バイトのid
0x00, 0x03, // ChangeRequest 
0x00, 0x04, // attibuteのボティのサイズ 4
0x00, 0x00, 0x00, 0x06// 送信先のアドレスとポートから返信する
};



以下のような返答をレスポンスを受け取る事ができます。

{
0x00, 0x00, // 最初の2バイトがは0
0x01, 0x01, // Bindingレスポンスを意味する。0x101 
0x00, 36, // length
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, //id
// 
0x00, 0x04// レスポンスをしてくれたサーバーのアドレスを意味する(SOURCE_ADDRESS)
0x00, 0x08, //length
0x00, 0x01, //family
0x03, (byte)(0xFF&0x20), //レスポンスしてくれたポート
127, 0, 0, 1,//レスポンスしてくれたアドレス
//
0x00, 0x01, // サーバーから見えたクライアントのアドレス(MAPPED_ADDRESS),
0x00, 0x08, //length
0x00, 0x01, //family
0x03, (byte)(0xFF&0x20), //サーバーから見えたクライアントのポート
127, 0, 0, 1,//サーバーから見えたクライアントのアドレス
//
0x00, 0x05, // STUNサーバーが持つ、異なるポートと異なるアドレス(CHANGE_ADDRESS)
0x00, 0x08, //length
0x00, 0x01, //family
0x03, (byte)(0xFF&0x20), //port
127, 0, 0, 1,


};

うけとったレスポンスを元に、自身がフルコーンなのか判定できます。判定するのは、STUNサーバーではなく。STUNクライアントであるところに注意してください。
今回の場合、このレスポンスを受け取る事ができたならば、フルコーンであると言えます。

参照検証ように作成したコード

https://github.com/kyorohiro/Hetimatan/blob/master/Hetimatan/src_nat/net/hetimatan/net/stun/HtunServer.java


まとめ/次回予告


という事で、STUNの正体は見えてきたでしょうか。
基本的な考え方は、「様々な条件で通信ができるか試してみ。どの条件で通信できたかで分類する」と行ったものである事が理解できたでしょう。

次回は、UDPパンチについて解説します。通信に細工をする事でNATをだまして、通信できるようにするテクニックです。






1 件のコメント:

  1. 微妙に、受け渡しするメッセージが間違っている。
    todo 訂正すること

    返信削除

mbedtls dart の 開発を始めた web wasm ffi io flutter

C言語 で開発した機能を、Dart をターゲットとして、Web でも サーバーでも、そして Flutter  でも使えるようにしたい。 そこで、mbedtls の 暗号化の部分を Dart 向けのPackageを作りながら、 実現方法を試行錯誤する事にした。 dart...