こんにちは!がねこまさしです。前回は複数人の同時通話まで実現しました。社内で使うには十分なレベルです。
しかし本格的な企業ユースとなると、まだまだ障害があります。会社と家、自社と別の会社さんなど、実際に通信しようとするとNATやFirewallといった壁が立ちはだかります。
NATを越えよう
NATの役割は
NAT(+IPマスカレード)は企業だけでなく、一般家庭でも使われています。ブロードバンドルーターやWiFiルーターでは、1つのグローバルIPアドレスを、複数のPCやデバイスで共有することができます。このとき、NATには2つの役割があります。
- インターネットにつながったグローバルなIPアドレスと、家庭内/社内のローカルなネットワークでのIPアドレスの変換
- 複数のPC/デバイスが同時に通信できるように、ポートマッピングによるポート変換
WebRTCでNAT越しに通信すること考えてみましょう。
ブラウザが知っている情報
- ローカルネットワークのIPアドレス:A
- 自分が使う(動的に割り振った)UDPポート:A/UDP
ブラウザでは分からない情報
- グローバルIPアドレス:A’
- NATによってマッピングされた、外部に向けたUDPポート:A’/UDP
Peer-to-Peer通信を行うには、シグナリング処理でお互いに(ローカルネットワーク内の情報ではなく)インターネット側から見た情報を通知する必要があります。
ブラウザーが、インターネット側から見た情報を知るための仕組みが、STUNになります。
STUNの仕組みは
STUNの仕組みは意外とシンプルです。インターネット側にいる誰か(STUNサーバー)に、自分(ブラウザ)がどう見えるか教えてもらうだけです。
STUNは元々WebRTCのために作られた仕組みではなく、より汎用的なUDP通信の補助として生まれました。VoIPやネットワークゲームの世界でも使われているようです。
自分を外側から見た情報が分かったら、それをシグナリングサーバー経由で通信相手に渡します。
お互いの情報が伝わったら、そこを目掛けて通信を行います。間にNATが挟まりますが、ポートを直接マッピングしているのであくまでもPeer-to-Peerです。
STUNサーバーを動かそう
それでは実際にSTUNサーバーを動かしてみましょう。Linuxで動作するオープンソースのものがあるので、そちらを使います。
rfc5766-turn-server
このサーバはSTUNだけでなく、後程説明するTURNにも対応しています。
DownloadページからOSに合わせたgzファイルをダウンロードし、INSTALL手順に従ってビルド、インストールしてください。参考までに以前私が実施した手順を載せておきます。※ちょっと古いバージョンです。最新のものを取得してインストールしてください。
CentOSの場合、以下の場所に導入されました。
次に設定ファイル( /etc/turnserver/turnserver.conf )を見てみましょう。ポイントとなるのは次の箇所です。
TCPとUDPの両方で待ち受けできますが、STUNはUDPのみが有効なので注意が必要です。※つまりUDPが通らない環境ではSTUNは使えません。
STUNはPeer-to-Peer通信が始まればサーバーのCPU負荷、ネットワーク負荷はかかりません。それに対して後述するTURNでは特にネットワーク負荷がかかります。サーバーを借りていてネットワーク通信量で課金されるようなケースでは、stun-onlyを設定してTURNは無効にしておいた方が良いかもしれません。
設定がすんだらSTUNサーバーを起動してみましょう。画面にエラーが出なければ無事に起動成功です。エラーが出る場合は turnserver.conf を確認してみてください。
クライアントのソースを修正しよう
ここまでで準備したSTUNサーバーを使うように、クライアント側のソースを修正しましょう。前回のソースの一部を変更します。
STUNサーバーが stun.yourdomain.com で、デフォルトのポート3478で動いていると仮定します。その情報をPeerConnectionに教えてあげます。
さあ、これで接続を試してください。上手く行けば、自宅と友人の家で通信が可能になっているはずです。
STUNでNATを越えられないとき
NATにはグローバルIPアドレスを共有するだけでなく、セキュリティ対策としての役割もあります。内部の端末を隠したり、通信できるポートを制限したり、一種の簡易Firewallとして利用されているケースもあります。その場合はFirewallの場合と同じく、次に説明するTURNを利用する必要があります。
また、NATの構造によっては、接続先によって(今回の場合、STUNサーバーとPeer-to-Peerの通信相手)別のポートが割り当てられる Symmetric NAT という物があります。この場合もSTUNの仕組みでは通信することができません。やはりTURNの出番ということになります。
Firewallを越えよう
一般家庭のようにブロードバンドルーターなどでNATがある環境では、STUNを使えば通信が可能になります。次は一般的な企業で使えるようにしましょう。
企業ではFirewallが設置されているケースがほとんどです。その場合、外部と通信できるポートも制限されます。STUNではUDPポートは動的に割り振られるままなので、Firewallにとても大きな穴を空けないと通信ができません。きっとセキュリティ管理者に怒られてしまいます。こんなケースに対応するのが、TURNの仕組みです。TURNもWebRTCのために生まれたのではなく、VoIPやネットワークゲームの世界で使われていたものです。
TURNの仕組みは
TURNを使った通信では、TURNサーバが実際のストリームデータを受け渡す間に入ります。すべてのパケットをTURNサーバーがリレーすることになり、もはやPeer-to-Peer通信ではなくなります。この際TURNサーバーでは動画のエンコーディングは行わないので、CPU負荷よりもネットワーク負荷が高くなりやすいです。
Firewallに穴を空けよう
TURNを使うには、Firewallに1つ穴を空ける必要があります。標準では3478/UDPを使うので、そのポートが通過可能になるように設定して(してもらって)ください。
もう1つ、シグナリングサーバーと通信するための穴も空ける必要があります。例えば9000番を使うのであれば、9000/TCPも同様に通過可能になるように設定して(してもらって)ください。
会社間で通信するのは、両方の会社でFirewallに穴を空ける必要があります。
※これを読んで「結局Firewallをいじるのかよー」とがっかりした人もいますよね? Firewallをいじらない方法もあるので、最後までお楽しみに。
TURNサーバーを動かそう
TURNサーバーは先ほどSTUNサーバーとしてインストールしたrfc5766-turn-server
がそのまま使えます。/etc/turnserver/turnserver.conf の設定を変更してTURNとして使える様にします。
デフォルトのポートは3478ですが、自由に設定できます。
TLS/DTLSは今回は使わない設定にしておきます。また先ほどのSTUNを動かす際に stun-only を設定した場合は、再びコメントアウトしてTURNも使える様にして下さい。
そして、WebRTCでTURNを使う際のキモはこちらの設定です。
なかなか lt-cred-mech が必須だとは分からず、とても長い間悩んでしまいました。lt-cred-mech で使用するアカウント情報はPostgreSQL, MySQL, Redisなどで管理できますが、今回はシンプルにファイル管理にします。
/etc/turnserver/turnuserdb.conf を使うことにしたので、その内容も変更します。
例としてユーザID: yourid 、パスワード: yourpassword としました。 ※実際にはもっと強度の高いパスワードにしてくださいね。
これで turnserverを再起動すれば、TURNでの通信が有効になります。
※ちなみに turnserverを安全に停止させる手段が分かりません。仕方がないので kill で殺しています…。
クライアントのソースを修正しよう
ここまでで準備したTURNサーバーを使うように、クライアント側のソースを修正しましょう。STUNで修正した部分と同じ個所になります。 STUN/TURNサーバーが turn.yourdomain.com で、デフォルトのポート3478で動いていると仮定します。その情報をPeerConnectionに教えてあげます。(STUNとTURNの両方を候補にすることができます)
さあ、これで接続を試してください。上手く行けば、会社と自宅、あるいは会社と友人の会社で通信が可能になります。
Firewallはそのままで
実際の企業ではセキュリティ上の制約や手続き上の問題で、Firewallに穴を空けるのが大変なことも多々あります。お客様の会社だったらなおさらですよね。そんな時のために、TURN over TCP という規格があり、rfc5766-turn-server と Chrome の両方ともサポートしてます。これを使えば、Firewallはそのままで、通信が可能になります。
TURNサーバを設定し直そう
設定が終わったら、turnserverを再起動してください。
クライアントのソースを修正しよう
ここでは省略しますが、シグナリングサーバーも 80/TCP で動かす必要があります。サーバー側のNode.jsのポート番号と、クライアント側のsocket.ioのつなぎ先のポート番号を80番に変更してください。※Webサーバー、シグナリングサーバー、TURNサーバーの3つをすべて80/TCPで動かすので、サーバーを3つ別々に立てる必要があります。頑張ってください。
さあ、これで最後です。ブラウザをリロードしてください。きっと壁を越えて対話ができることと思います。
最後に
これまで全5回、WebRTCの使いかたを説明してきました。開発者向けにコードを一から書いてきましたが、世の中には便利なライブラリやサービスも数多くあります。
こちらを利用するのもありですね。日本でWebRTCが盛り上がって、企業ユースでも認知されるのを期待しています。
おつきあいいただき、どうもありがとうございました。