要約
- WebRTC で使われる TURN サーバーで日本-ブラジル間を中継
- coturn を Google Cloud Platform 上に構築
- coturn サーバーの external-ip 設定が重要
はじめに
インダストリー事業本部のイチノです。業務では、リモート製品 (Optimal Remote, Optimal Second Sight, ポケットドクターなど遠隔地とコミュニケーションするための製品) で使われるコア技術をまとめた Communication SDK を担当しています。 Communication SDK では、映像や音声の送受信用に WebRTC を利用しています。 WebRTC では、ピア(参加者)同士が接続できるように STUN/TURN サーバーを利用して、通信しています。
今回は、日本-ブラジル間を TURN サーバー同士の接続について紹介します。日本から地理的に最も遠いブラジルとの通信を想定し、 WebRTC の通信を確認してみたいという興味が発端です。せっかくなので、以前から個人的に気になっていたTURN同士が通信するということも確認してみました。TURNサーバーの振り分け方法については今回の対象とせず、案だけを最後に書いています。
所感
- 今回、試すまで、TURN サーバー同士が繋がるということについて半信半疑でしたが、繋がるのを目の当たりにして驚きました。
- これ、ディザスタリカバリに使えるじゃんと思いました。
TURNサーバーについて
WebRTC では、ピアが通信するためにNAT越えする必要になる場合があります。NAT 超えするために、
- STUNサーバーでのホールパンチを利用したP2P通信
- TURNサーバーでのデータ中継
のいずれかで、ピア同士を通信させます。WebRTCは、可能な限りP2P通信を行ます。P2P通信に失敗する場合、TURNサーバーにピア間の通信を中継させます*1。WebRTCの前身であるlibjingleでは、
- 92% が STUN を使った P2P 通信
- 8% が TURNによる通信
が利用されていました*2。TURNサーバーを使うことで、P2P通信で接続できない通信環境に対処できます。このため、 WebRTC を使ったサービス提供時に TURN サーバーは重要な役割を持ってきます。TURNサーバーの動作、TURN 同士が通信する理由については、以下の WebRTCの裏側が参考になります。
TURNサーバーの準備
TURNサーバーを Google Cloud Platform 上に構築しました。構築したインフラを以下に示します。
Google Cloud Platform のVPC(Virtual Private Cloud) 配下へ、日本に VM 1台、ブラジルに VM 1台を配置しています。インターネットからのアクセスに対して、VPCがVMにアクセスを振り分けます。マシンタイプは、テスト環境用にいずれも最小構成のf1-micro(vCPU x 1、メモリ 0.6 GB)を利用しています。VPC 内部のネットワーク設定についてはデフォルト設定を利用しました。内部 IP アドレスについて設計意図は、ありません。 VPC に設定するファイアウォールには、TURN サーバー疎通用に上り tcp:3478 と udp:3478 を許可しています。
利用する TURN サーバーには、 coturn を利用します。 coturnのインストール方法については、省略します。coturn を各VMへインストールします1。構築したインフラに合わせた coturn サーバーの設定を以下に示します。
# ①テスト環境なので、STUN機能を無効化。 no-stun # ②認証を有効化。 WebRTC では必須の設定。テスト環境ですので、認証情報を turnserver コマンドの引数で渡します。 lt-cred-mech # ③ verbose ログを表示 verbose # ④ TURN の IP アドレス。内部 IP アドレスを設定しています。 relay-ip=10.240.0.8 # ⑤ 外部のピアに教える TURN サーバーが待ち構えるIPアドレス。 # VPC 配下で TURN サーバー同士を通信させるための重要な設定です。 # 値は、自機の内部IPを設定してください。 external-ip=10.240.0.8 # ⑥ TURN サーバーの受信ポート listening-port=3478 # ⑦ 使用する UDP ポートの範囲指定 min-port=49152 max-port=65535
重要な設定は、⑤の external-ip 設定です。 external-ip で指定した IP アドレスが、TURNの接続候補 (ICE Candidate) としてピアに報告されます。接続候補が相手ピアに通知され、相手ピアのTURNが接続します。なお、 external-ip には、自機の内部 IP (ローカル IP)を設定してください。例えば、日本側のVMであれば、 10.240.0.8 を、ブラジル側の VM であれば 10.240.9 を設定します。もちろん、自機に割れ当てられた外部 IP (グローバル IP)を設定できます。
今回構築した環境で、外部 IP ではなく内部 IP を設定した理由は、次の通りです。
- Google Cloud Platform の VPC の 1 つの特徴である高速な帯域を利用したいから *3
- VPC の管理されたネットワークなので、 TURN サーバー間の通信に関して、外部 IP アドレスを経由するよりも、閉ざされたネットワークでの接続を実現できるから
最後に、turnserver コマンドで起動します。オプションには、TURN サーバーの認証情報を設定しています。
$ turnserver -c turnserver.conf --user user1:pass1 --realm=tekitouna_realm
TURN サーバー利用手順
ピアが、別々の TURN サーバーに接続して、 WebRTC のビデオチャットできることを確認していきます。 WebRTC の接続の確認には、 AppRTC を利用します。
AppRTC を使わない方は、この章を読み飛ばしていただいて結構です。AppRTCを利用した理由は、単に WebRTC接続のプログラム実装やシグナリングサーバーの実装が面倒だったからです。
少々本題から逸れますが、 AppRTC での TURN サーバー設定方法について触れておきます。 AppRTC には、任意の TURN サーバーを設定できます。他のパラメータについては、https://apprtc.appspot.com/params.html をご覧ください。 https://appr.tc/?ts=https://turn.example.org/some_path の様に ts パラメーターを指定すると appr.tc のサイトは、XHR(XMLHttpRequest) で、 https://turn.example.org/some_path/v1alpha/iceconfig?key=randomchars へ POST リクエストを発行します。レスポンスボディーを JSON としてパースし、パース結果を RTCPeerConnection の引数として渡します 2 。 appr.tc が期待している JSON データは、次の通りです。
{ "iceServers": [ { "urls": ["turn:203.0.113.1:3478"], "username": "user1", "credential": "pass1" } ], "iceTransportPolicy": "relay", "iceTransports": "relay" }
RTCIceServer と同じ値を iceServers に設定できます。 urls に構築した TURN サーバーを設定します。 username と credential は、必須です。また、iceTransports には relay を設定します。 JSON を返すサーバーを、パスごとに日本かブラジルの TURN サーバーへ向ける設定を返すように設定しておいてください。あとは、AppRTC の ts パラメータに適切なパスを含んだパラメーターで開くと、日本かブラジルの TURN サーバーへ接続してくれます。以上が、 AppRTC での TURN サーバー設定方法です。
TURN サーバー通信の確認
通信の確認に利用した環境を、以下の図に示します。図中から、 VPC や、シグナリングサーバー、 AppRTC を説明のために省いています。
NAT配下に存在するピアが、TURNサーバー(coturn) を経由して接続します。ピアはいずれも日本国内から TURN サーバーへアクセスします。計測をしないので、気にしないでください。ピア 1 は、ブラジルの TURN サーバーに接続するピアです。ピア 2 は、日本の TURN サーバーに接続するピアです。接続したときに、 chrome://webrtc-internals を開くことで、 WebRTC の通信状態を確認できます。ピア 1 とピア 2 の通信状態を確認したときのスクリーンショットです。
図中の赤枠の部分 googLocalAddress と googRemoteAddress が内部 IP 同士で接続しあっています。 体感では、 2 秒から 3 秒の遅延が発生していました。6秒ほどの遅延が発生する時もありました。両ピアが日本にいる関係で、パケットが日本-ブラジル間を往復しており、遅延についてはまずまずといったとこでしょう。
TURN サーバーの振り分け方法
TURNサーバーの振り分け方法は、DNSラウンドロビンによる振り分けや、TURN/STUNサーバー情報をWebサーバー側で振り分ける方法が考えられます。また、クラウドサービス依存になりますが、 Google Cloud Platform の Load Balancing による振り分けが考えられます。今回は、試していません。
おわりに
ピアは2台とも日本に在りましたが、片方のピアが日本に設定したTURNサーバーを経由し、もう片方がブラジルに設置したTURNサーバーを経由した通信を確認できました。世界各地にTURNサーバー配置することで、WebRTCを使ったサービスをより安定して提供できると考えられます。
オプティムでは、 WebRTC 限らず様々なことに興味があるエンジニアを募集しています。
脚注・参考文献
*1:“Real time communication with WebRTC”,< https://codelabs.developers.google.com/codelabs/webrtc-web/#0 > , 2019年2月10日アクセス
*2:Ilya Grigorik 著、和田 祐一郎/株式会社プログラミングシステム社 訳(2014), 『ハイパフォーマンス ブラウザネットワーキング ネットワークアプリケーションのためのパフォーマンス最適化』, 株式会社オライリー・ジャパン.
*3:“ここまできた ! Google Cloud Platform Virtual Private Cloud 徹底解説 - YouTube”, < https://www.youtube.com/watch?v=jMQsrEQuhOU&t=427 > , 2019年2月10日アクセス