閉域網でWebRTCを使う際の勘所

# はじめに

withコロナ時代を迎えて、WebRTCを利用したビデオ通話や音声通話の需要はかなり伸びています。
その中で最近よく聞くようになってきたのは、閉域網内でWebRTCを利用した通話をしたいという話です。
閉域網はPublicなインターネットには直接繋がれておらず、限られた利用者や拠点家のみを接続するプライベートネットワークのことで、VPNともいいます。

この記事では、WebRTCをVPNで利用する際の各種Tipsをまとめます。

# VPNの種類

## 接続レイヤー

VPNには色々な方式があります

- L2接続
    - 広域イーサネットVPN
        - 通信事業者の閉域網を利用する
        - 設定・構築は煩雑だが通信プロトコルにIP以外を利用できるなど汎用性は高い
- L3接続
    - IP-VPN
        - 通信事業者の閉域網を利用する
        - クローズドなので安心感がある
    - インターネットVPN
        - 通信網にパブリックなインターネット回線を利用する
        - 安価に構築できる反面セキュリティリスクも存在する

参考:[VPNの分類や特徴](https://qiita.com/yuyasat/items/81c32d7e235af97515c0)

WebRTCはIPレイヤー上で動作するプロトコルになるため、L3接続のVPNでの利用にフォーカスを当てていきます。

## 参考: 用途別の閉域網サービス

参考までに、企業が独自にVPN等を導入するパターンもありますが、以下のような用途別の閉域網サービスを利用し、その上でWebRTCを使いたいという事例もよく耳にします。

- LGWANを中心とした地方公共団体向けの閉域網
    - https://www.j-lis.go.jp/data/open/cnt/3/180/1/L-2_gaiyou_Internet_201804.pdf
    - 各行政団体のLANを相互に接続
    - インターネットから切り離された閉域網

- SINET
    - https://www.sinet.ad.jp/aboutsinet
    - 学術情報ネットワーク
    - 大学などの教育機関を相互に接続

# VPNでWebRTCを使う際の勘所

WebRTCによる通信を実現するためには、シグナリング、STUN、TURN、SFUというコンポーネントが必要になりますが、それぞれの観点で勘所をご紹介します。

## シグナリング

WebRTCは歴史的経緯からシグナリングの手法が規定されていません。[手動](https://qiita.com/yusuke84/items/43a20e3b6c78ae9a8f6c)含め、どのような方法でシグナリングをしても問題ありません。また、手軽に利用可能なWebRTCプラットフォームサービスも存在するため、それらを利用することもあるでしょう。

自身でシグナリングサーバを構築構築する際はVPN内にそのサーバを設置すればよいのですが、インターネットからのパブリック接続を前提にしているWebRTCプラットフォームサービスを利用している場合は、VPN内の端末からプロキシサーバ等を介しながら、そのサーバまでのネットワークリーチを確保する必要があります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/6651/0f3fb681-91f5-20f9-ab28-797e701e1719.png)


尚、VPN接続に対応したWebRTCプラットフォームも世の中には存在するかもしれません。しかしながら、通信経路がVPNを通るというだけでサーバ設備自体はシェアードサービスだと思うので、本当の意味で閉域にしたい場合は、自分たちのVPN内にWebRTCサーバ一式を構築することになりそうです。そこにこだわりがなければ、何らかの方法でインターネットに抜けてシグナリングサービスを利用する形がコスパが良いと思います。

## TURN

VPN内での通信の場合は、VPN内でのP2P通信を前提にすると思うので、TURNサーバの出番は少ないと思います。よく、社内ネットワークからインターネットに出る際にプロキシサーバが介在していて、そこを通すためにTURNを使うという話はありますが、網内折返しの場合はスルーすることが多いと思うので、特別に考慮はしません。

## SFU

SFUを使うかどうかはユースケース次第になりますが、VPN内に限定した多人数通話や配信などを行いたい場合は利用することになると思います。

VPNでSFUを利用する場合はシグナリングと同じく、WebRTCプラットフォームサービスを利用するか、自身で構築するかの２択がありますが、SFUの場合は通信プロトコルが特殊であることと、メディアのトラフィックが流れることから、インターネットに抜けてWebRTCプラットフォームサービス事業者が用意した設備を使うのはハードルが高いかもしれません。

自身で構築する場合は、OSSのSFUを自分でホスティングする、商用のソフトウェアを使ってホスティングするという選択肢があります。後者は国内だと、時雨堂の[Sora](https://sora.shiguredo.jp/)が有名ですね。

## P2P（STUN）

最後は、VPN内でのP2P通信についてです。
IP-VPNであれば気にする考慮する必要はありませんが、インターネットVPNの場合は必ずしもVPN経由の通信経路を通るわけではないので注意が必要です。

WebRTCはIPレイヤーの上で動作するICEというプロトコルを利用して通信経路を確立します。
ICEではCandidateと呼ばれる通信経路の候補を収集し、それにプライオリティをつけて、高優先の経路から順に通信経路確立を試行していきます。

以下は、VPN接続時とそれ以外の時でCandidateを収集した結果です(カッコの注釈はこちらで加えています)。

- VPN接続無し

```
0.003	1	host	3407114347	udp	192.168.43.5(プライベートIP)	54974	126 | 32542 | 255
0.105	1	host	2241301659	tcp	192.168.43.5(プライベートIP)	9	90 | 32542 | 255
0.656	1	srflx	1023674815	udp	49.98.220.84(通信キャリアのIP)	54974	100 | 32542 | 255
0.717	1	relay	4094808562	udp	35.221.69.45(TURNサーバのIP)	55874	2 | 32543 | 255
0.802	1	relay	4265599350	udp	34.85.43.166(TURNサーバのIP)	25386	1 | 32544 | 255
0.941	1	relay	3769543683	udp	34.85.43.166(TURNサーバのIP)	42773	0 | 32542 | 255
```

- VPN接続有り

```
0.001	1	host	3407114347	udp	192.168.43.5(プライベートIP)	58515	126 | 32542 | 255
0.002	1	host	3565987522	udp	xxx.xxx.xxx.xxx(VPN内のプライベートIP)	53567	126 | 32286 | 255
0.103	1	host	2241301659	tcp	192.168.43.5(プライベートIP)	9	90 | 32542 | 255
0.103	1	host	2584697394	tcp	xxx.xxx.xxx.xxx(VPN内のプライベートIP)	9	90 | 32286 | 255
0.745	1	srflx	1023674815	udp	49.98.220.84(通信キャリアのIP)	58515	100 | 32542 | 255
0.747	1	srflx	580706070	udp	yyy.yyy.yyy.yyy(VPN内のインターネットGW)	11950	100 | 32286 | 255
0.747	1	srflx	580706070	udp	yyy.yyy.yyy.yyy(VPN内のインターネットGW)	3618	100 | 32286 | 255
0.836	1	relay	3449923731	udp	34.84.25.120(TURNサーバのIP)	37172	2 | 32543 | 255
0.837	1	relay	3449923731	udp	34.84.25.120(TURNサーバのIP)	21544	2 | 32287 | 255
0.961	1	relay	763094951	udp	35.194.111.46(TURNサーバのIP)	26107	1 | 32288 | 255
1.123	1	relay	871017170	udp	35.194.111.46(TURNサーバのIP)	39936	0 | 32286 | 255
```

一番右の３つの数字がプライオリティ情報です。
プライオリティの計算ロジックは[RFC8445#section-5.1.2.1](https://tools.ietf.org/html/rfc8445#section-5.1.2.1)に記載されていますが、並び替えのキーになるのは一番左の数字、type preference（server reflexive, peer reflexive, relayed, and host）です。それぞれの意味合いは以下のとおりです。

- host(host)
    - NICに付与されているプライベートIP
- server reflexive(srflx)
    - STUNを利用して収集した何らかのグローバルIP
- peer reflexive(prflx)
    - UDPホールパチング中に発見された通信可能なIP
- relayd(relay)
    - TURNサーバのリレー用IP

VPN無しの場合は以下の通りなので、NAT無しで直接通信できる相手であればhostが利用され、それ以外の通信はsrflxが使われます(relayの話は今回は省略)。

> host: 192.168.43.5
> srflx: 49.98.220.84


VPN有りの場合がややこしいのですが、以下のようにhost候補とsrflex候補がVPN経由の場合と、それ以外の場合で２つ出てきます。
VPNの設定にもよりますが、VPN接続中は端末のデフォルトゲートウェイがVPN経由に書き換えられ、ネットワークIFを指定すれば、インターネット経由での接続も可能という状況になる場合が多いのではないでしょうか。私の環境がまさにそういう環境なので、Candidateとしては２候補収集されました。

> host: 192.168.43.5
> host: xxx.xxx.xxx.xxx(VPN内のプライベートIP)
> srflx: 49.98.220.84(通信キャリアのIP)
> srflx: yyy.yyy.yyy.yyy(VPN内のインターネットGW)

時と場合によるとは思いますが、この状況で以下のパターンの接続を試みると、いずれの場合もインターネット経由（通信キャリアのIP）で接続されてしまいました。

VPN接続の端末A↔VPN接続の端末B
VPN接続の端末A↔インターネット接続端末C

時と場合によるというのは、Candidateを集めてUDPホールパチングで最速で穴開け（経路確立）を試みるため、その時々の状況次第では別経路で繋がる可能性があるということです。つまり、必ずVPN経由になるとは限らないということです。

WebRTCによるP2P通信はE2EEなのでVPNを経由せずにインターネット経由で流したい（むしろ負荷をかけたくない）、WebRTCによるP2P通信もセキュリティの観点（２重に暗号化したい）からVPNを経由させたい等、要件は様々だと思いますが、インターネットVPNの場合は経路制御をしなければ、思い描いた経路でつながらない可能性があるというのご理解いただいたほうが良いと思います。ここでいう経路制御で一番手っ取り早いのは、不要なCandidateを削除することになります。WebRTCプラットフォームサービスのSDKを使っている場合はハードルが高いかもしれません。