Edited at
WebRTCDay 14

TURN-TCP (TCP to UDP) について

More than 3 years have passed since last update.


概要

WebRTC の闇の一つである TURN/STUN の TURN サーバにおいて、通常の動作では UDP ですが、それを無理矢理 UDP over TCP で動作する仕組みがあります。

それを簡単に解説していきます。


TURN について

簡単に説明してしまうと NAT 越えを実現するプロトコルです。

WebRTC では UDP 通信を前提とした動作をするため、特定条件下では NAT 越えの必要性が出てきます。

通常であれば WebRTC は P2P での動作をしますが、特定の NAT 下では TURN サーバを経由(リレー)してしか通信をすることができません。

基本は P2P で通信ができる。ただし、いろいろな条件が重なると TURN を使う必要があるというイメージで問題ありません。


用語


  • クライアント


    • WebRTC ではブラウザです



  • サーバ


    • TURN/STUN サーバです



  • ピア


    • ブラウザ、または TURN/STUN サーバです




WebRTC で期待されている関連 RFC

WebRTC で求められている TURN の RFC は以下の通りです。そんなに多くありません。


RFC 6062

RFC 6062 はクライアントと TURN サーバの間、TURN サーバとピアの間両方を TCP で行う事がメインに定義されていますが、実際の WebRTC では TURN サーバとピアの間で TCP では動作しません。

WebRTC では RFC 6062 に定義されているもう一つの クライアントと TURN サーバの間は TCP で、TURN サーバとピアの間は UDP で行うといった動作が必要になります。

TURN サーバは TCP から UDP へプロトコルの変換を行う必要があります。

TCP ベースの TURN の動作

クライアント -> <TCP> -> TURN サーバ -> <TCP> -> ピア

TCP と UDP ベースの TURN の動作

クライアント -> <TCP> -> TURN サーバ -> <UDP> -> ピア


TCP to UDP

TURN サーバとピアのプロトコルは、クライアントがサーバに送ってくる TURN プロトコルの Allocation-Request と呼ばれるリクエストの中に含まれる REQUESTED-TRANSPORT 属性の値で決まります。

皆さんご存じのプロトコルナンバーがそのまま使用されています。

http://www.iana.org/assignments/protocol-numbers/protocol-numbers.txt

UDP であれば 17 、TCP であれば 6 ですね。

2014-11-24 現在、WebRTC ではこの REQUESTED-TRANSPORT には 17 、つまり UDP が含まれています。

そのため TURN サーバからピアへのアクセスは UDP になります。


TURN サーバまでのプロトコルはクライアントが決める

ここで注意して貰いたいのはクライアントと TURN サーバのプロトコルはクライアントが決めるという事です。

そのため、サーバは UDP でも TCP でも TLS でも待ち受けている必要があります。

クライアントがどのプロトコルで要求してきても問題ないような実装にする必要があります。


TURN サーバの動作

TURN サーバを使う場合、 STUN と ICE の知識はとくに必要ありません。 TURN サーバが色々隠蔽してくれるためです。

TURN サーバの簡単な動作を箇条書きにしてみました。


  • Allocation-Request で依頼してきたクライアント専用のリレーサーバを作成する

  • CreatePermission-Request でリレーサーバのパーミッションを設定する

  • ChannelBind-Request でリレー用の CHANNEL-NUMBER を設定する

基本的にはこの 3 つが動作して、後はデータのやりとりを行うだけです。


リレーサーバ

TURN のポイントはリレーサーバです。クライアント毎に動的にリレーサーバを作成してくれます。

ポートを動的に開くのでなかなかリソース管理がやっかいだったりします。範囲も RFC で決められています。

基本的にはエフェメラルポートを使います。


TURN-TCP (TCP to UDP) の疑問


TCP to UDP だとそもそも UDP が通らないのでは ...

結論から言えば問題は出ません。

TURN サーバはプロトコル的には一方向のプロトコルです。WebRTC で 1:1 で通信を行うとき、両方に TURN サーバが必要となった場合は、実はリレーサーバが 二つ 起動しています。

つまりそれぞれのクライアントは TURN サーバまで TCP で接続しています。そして TURN サーバ同士で UDP で通信するのです。同一の TURN サーバにいれば UDP ではありますが、ループバックになります。そのため NAT は関係なくなります。

クライアントA -> <TCP> -> TURN サーバ -> <UDP> -> TURN サーバ -> <TCP> -> クライアント B

上記の動作では、実際はクライアント A も B も TCP で TURN サーバにつないでいるため NAT を基本的には考慮する必要はありません。

TURN サーバ同士と書きましたが、具体的にはリレーサーバ同士が通信します。

クライアント A -> <TCP> -> TURN サーバ -> TURN リレーサーバ A -> <UDP> -> TURN リレーサーバ B(ピア) -> TURN サーバー -> クライアント B

少しややこしいですが、UDP 通信が使われているのは TURN サーバ上となり、NAT ってなんだっけ状態になります。


TURN-TLS (TLS -> UDP)

とくに難しい事はなく TCP がそのまま TLS になると考えて問題ありません。

turns というスキームを使います。WebRTC は turns に対応しています。

用途としては、外部に出られる通信が TLS のみなどと規定されている場合です。あまり無いと思いますが ... 。

WebRTC の通信は DTLS で暗号化されているため、それを TLS でやりとりするのはどうなんだと思ったりしますが。まぁそこは大人の事情なのであまり触れないことにします。


まとめ

WebRTC の闇の一つである TURN サーバの動作の一つである TURN-TCP についてざっくりと解説してみました。

プロトコルはそんなに複雑ではありません。細かい動作はかなり実装するには面倒くさいですが使う分にはとくに気にすることはありません。

TURN サーバが無いと通信が出来ない環境の割合は不明ですが、一定数以上あると思います。WebRTC のサービスを提供する際は必須になると思います。

興味があれば RFC を読んでみることをオススメします。


参考