TURNサーバへのコネクティビティを確認する方法

# はじめに

WebRTC界隈では有名な、ブラウザのWebRTC機能を試すためのサンプル集があります。

- Webサイト: [WebRTC samples](https://webrtc.github.io/samples/)
- ソースコード: [https://github.com/webrtc/samples](https://github.com/webrtc/samples)

今日はこのサンプル集から、 [Trickle ICE](https://webrtc.github.io/samples/src/content/peerconnection/trickle-ice/)のテストを行うサンプルを使ったネタを紹介します。

# Trickle ICEのサンプルについて

今回はこのTrickle ICEのサンプルを利用して、SkyWayのTURNサーバへのコネクティビティを確認してみます。TURNサーバって何？Trickle ICEって何？という方は [WebRTCハンズオン 概要編](https://qiita.com/massie_g/items/916694413353a3293f73) を一読することをおすすめします。

まず、このサンプルを使ったことがない方のために、使い方を簡単にご説明します。Trickle ICEにアクセスすると以下のような画面が出てきます。

![スクリーンショット 2018-12-27 12.46.16.png](https://qiita-image-store.s3.amazonaws.com/0/6651/c9349e2b-6e21-9fde-54d4-8c641a155181.png)

ICE serversにICEで利用するSTUN/TURNサーバを追加し`Gather candidates`ボタンをクリックすると、そのサーバを利用してCandidate(経路情報)の収集を行ってくれます。Trickle ICEなので、`onicecandidate`のイベントが発火するタイミングで、収集した経路情報を画面に出力します。そして、 `onicegatheringstatechange `のイベントを監視し`iceGatheringState`が`complete`になったら、収集作業終了となります。

このツールは、ブラウザのWebRTC実装におけるICE機能をテストするためのものですが、WebRTCを利用するエンドユーザーのネットワーク環境の確認にも利用できます。例えば、エンドユーザーのネットワーク環境でP2P通信が出来るのか、TURNサーバを利用した通信ができるのかについては、ICEで通信に必要な経路情報が収集出来るか否かである程度判断が可能です。

# P2P通信のための経路情報を収集する

P2Pの経路情報の収集については、このツールでデフォルト設定されている、Google提供のSTUNサーバ `stun:stun.l.google.com:19302` を利用することで可能です。このような感じで収集できます。

![スクリーンショット 2018-12-27 13.20.08.png](https://qiita-image-store.s3.amazonaws.com/0/6651/18e71048-b9fe-a2fd-0e17-fa27287e8ecc.png)

Component Typeに`host`と書かれているものはLAN上の経路情報で、パソコンの物理NICや仮想NICの情報をブラウザが収集したものです。`srflx`はSTUNサーバを利用して確認したNATを経由する経路情報です。同一LAN内でWebRTC通信する際は、`host`の経路を利用するのがもっともコストが掛からないためそのように動きますが、別ネットワークやインターネットを介して通信する際は、`srflx`の経路を利用することになります。

超余談ですが、2018年8月頃に[Gigazine - VPNでもWebRTC経由でIPアドレスが漏洩するとセキュリティ専門家が警告、漏洩の危険があるVPNも公開](https://gigazine.net/news/20180330-vpn-leak-via-webrtc/)で話題になった事象は、このICEの仕組みを利用すると、VPN接続しているにも関わらず、VPNによる通信経路以外の経路情報もブラウザが収集し、最終的に通信コストが低ければそちらの経路でWebRTC通信が行われてしまう可能性や、その経路情報が外部に漏れることで攻撃者に悪用されてしまう事を危惧しているようです。実際問題、WebRTC通信に関して言えば、End-to-Endで通信内容は暗号化されているので、内容が盗み見られる可能性はかなり低く、気にするかどうかは利用者やその所属組織のセキュリティポリシー次第なのではないかと、個人的には思います。

**WebRTC漏れ**という言葉で情報発信されているExpressVPNさんの[WebRTC漏れテスト](https://www.expressvpn.com/jp/webrtc-leak-test)は、このTrickle ICEのサンプルと同じ仕組みを利用して、IPアドレスを収集しているようです。

![スクリーンショット 2018-12-27 13.39.55.png](https://qiita-image-store.s3.amazonaws.com/0/6651/4c865957-0af3-40ed-b064-d1d38ab4fd67.png)

# TURNサーバを利用する場合の経路情報を収集する

さて、今度は、P2P通信ができない環境の話です。
P2P通信ができない環境の場合（例えば、STUNサーバへのアクセスが許可されていない、UDP通信が禁止されている、プロキシで通信先が限定されている等）は、TURNサーバを中継させて通信を行うことになるのですが、そのTURNサーバへの通信が問題なくできるかも、このツールで調べることができます。ただし、TURNサーバは無償で公開されているものを利用するというのは難しいため、自分で建てるか、有償のものを利用することになります。今回は、SkyWay Community Editionで利用できるTURNサーバを利用してみることになります。

## SkyWayのTURNサーバに関する情報を収集する

SkyWayのTURNサーバのURIや認証情報を収集します。これは少々ハック的な事をする必要があります。こちらの[「SkyWayを使いこなすために」という資料のP70](https://www.slideshare.net/iwashi86/skyway-how-to-use-skyway-webrtc#70)で紹介されています。一応中の人なので、一言断っておくと…この仕様は将来変更になる可能性があります。ご了承下さい。

ここで取得した、TURNサーバに接続するための`URI`、`username`、`credential(password)`を用いてツール上でICE Serverを追加すればTURNサーバを利用してコネクティビティが確認できます。尚、`username`、`credential`についてはnew Peer()するたびに変わりますので、利用するたびに都度、取得する必要があります。

## Trickle ICEのサンプルのソースコードを書き換える

いろいろ端折りますけど、Trickle ICEのソースコードをちょちょっと書き換えて自動でSkyWayのSTUNサーバ、TURNサーバがICE Serversにセットされるようにしてみました。

```javascript
const peer = new Peer({
  key:   'APIKEY',
  debug: 3,
});

peer.on('open', () => {
  urlInput.value = peer._pcConfig.iceServers[1].urls;
  usernameInput.value = peer._pcConfig.iceServers[1].username;
  passwordInput.value = peer._pcConfig.iceServers[1].credential;
  addServer();
  urlInput.value = peer._pcConfig.iceServers[2].urls;
  usernameInput.value = peer._pcConfig.iceServers[2].username;
  passwordInput.value = peer._pcConfig.iceServers[2].credential;
  addServer();
  urlInput.value = peer._pcConfig.iceServers[3].urls;
  usernameInput.value = peer._pcConfig.iceServers[3].username;
  passwordInput.value = peer._pcConfig.iceServers[3].credential;
  addServer();
});
```

コードは即席です。本来は、urlInput、usernameInput、passwordInputというinputエレメントにユーザが値を入力し、`addServer()`というfunctionを呼び出することで、ICE Serversの候補に追加されます。それを自動でやっているだけです。

それから、注意が必要なのですが、このサンプルはICE Serversの情報をブラウザのローカルストレージに保存する仕組みになっています。そのため、毎回利用するたびに前回のServer情報が表示されてしまいます。今回それは邪魔なので、無効化しました。

## 試してみる

[サンプル](https://yusuke84.github.io/samples/src/content/peerconnection/trickle-ice/index.html
)として公開しています。アクセスするとICE serversには自動でSkyWayのSTUNとTURNの情報が入りますので、`Gater candidates`をクリックするだけです。尚、ICE optionsで`relay`をデフォルト設定にしています。STUNサーバを利用した候補を収集したい場合は、`all`を選択して下さい。

![スクリーンショット 2018-12-27 14.20.21.png](https://qiita-image-store.s3.amazonaws.com/0/6651/5b209cf8-e7da-ca3e-1cac-9a2648656289.png)

収集を行うと、Component Typeに`relay`と書かれた、SkyWayのTURNサーバを利用する場合の経路情報が出てきます。尚、注意が必要なのは、ここで情報が表示されたとしても、この後のWebRTCの通信が100%成功する保証はありません。ただし、逆にここで情報が取得できなければ、この後のフェーズには進めません。

## 終わりに

WebRTCを本格的に運用するためには、こういうテストツールの存在が重要になります。特に、エンドユーザーの環境が高いセキュリティを要求する環境だったり、逆に不特定多数が利用するサービスでどんな環境で利用されるかが読めなかったりする場合は、エンドユーザー自らが実行できるテストツールを提供することで、事前の環境準備に役立ててもらったり、そもそも使えないんだという期待値コントロールができたり、トラブル発生時の切り分けに利用できたりします。そんな方々にとって、この記事が参考になれば幸いです。