WebRTC
WebRTC ・ うぇぶあーるてぃーしー
ブラウザ同士が NAT を越えて直接つながり、音声・映像・データを送り合うための標準技術。
✦ 30秒で試す — 航海家のルーターの内側どうしなのに、外を経由せずに直結できるつながるまでに、サーバの手助けは要る?予想してみる概要
WebRTC(Web Real-Time Communication)は、ブラウザ同士がサーバを経由せずに直接つながり、音声・映像・任意のデータをリアルタイムに送り合うための標準技術です。プラグインのインストールなしに、JavaScript からブラウザの API(RTCPeerConnection など)を呼ぶだけで、カメラやマイクの映像を相手のブラウザへ届けられます。Google Meet や Discord の通話など、ブラウザで動くビデオ会議・音声通話の多くが WebRTC の上に成り立っています。
最大の特徴は P2P(ピアツーピア)、つまり「端末同士の直接通信」を基本とすることです。ふつうの Web の通信はクライアントがサーバに要求して応答をもらう形ですが、WebRTC ではあなたのブラウザと相手のブラウザが直接パイプを結び、映像や音声のパケットが(うまくいけば)端末の間を最短経路で流れます。会話は遅延(レイテンシ)に敏感なので、再送で待たされる TCP ではなく、届かなかったものは諦めて先へ進める UDP を土台にしている点も、Web のほかの技術とは一線を画すところです。
ただし、家庭やオフィスの端末はたいてい NAT の内側にいて、外から直接話しかけることができません。WebRTC の仕組みの大半は、この壁をどう越えるかに費やされています。
なぜ生まれたか
WebRTC 以前、ブラウザでビデオ通話をするには Flash などのプラグインに頼るか、専用アプリを配るしかありませんでした。通信の方式の面でも、映像と音声をすべてサーバで中継すると、参加者が増えるほどサーバの帯域の費用が膨らみ、中継のぶんだけ遅延も増えます。会話は 200〜300 ミリ秒の遅延でも不自然に感じるため、「サーバを一往復余計に経由する」こと自体が体験の敵でした(レイテンシとスループットの話でいえば、レイテンシが主役の用途です)。
そこで Google が2010年に買収した音声・映像技術(GIPS)を2011年にオープンソースとして公開し、通話に必要な技術一式 — 音声・映像のコーデック、暗号化、NAT 越え — をブラウザに標準で積んで、端末同士を直接つなぐ仕様として WebRTC の標準化が始まりました(W3C と IETF の仕様は2021年に正式な標準になっています)。P2P にすれば中継サーバの帯域の費用が消え、経路も最短になって遅延が減る。「リアルタイム通信をプラグインなしの Web 標準にする」ことと、「サーバ中継の遅延と費用をなくす」ことを同時に狙った技術です。
詳細
最大の壁 — NAT 越えと STUN・TURN・ICE
P2P の理想は単純ですが、現実のインターネットには大きな障害があります。家庭やオフィスの端末はルータの NAT(プライベートな IPアドレスをグローバルなアドレスに書き換える仕組み)の内側にいるため、端末自身は「外から見た自分の住所」を知りません。しかも NAT は、内側から始めた通信の帰りしか通さないので、外から内側の端末へいきなり接続を張ることもできません。互いに NAT の内側にいる2台をどうやって直接つなぐか — これが WebRTC 最大の難所で、STUN・TURN・ICE という3つの仕組みで解決します。
STUN(Session Traversal Utilities for NAT)は「外から自分がどう見えているか」を教えてくれる軽いサーバです。端末が STUN サーバにパケットを送ると、STUN サーバは届いたパケットの送信元 — つまり NAT が書き換えた後のグローバルな IP アドレスとポート番号 — をそのまま返してくれます。NAT は、内側からパケットを一度出すと、その相手からの戻りを通す「穴」(変換テーブルの行)を開けます。そこで、互いに STUN で知った住所を交換し、双方から相手の住所へ向けてパケットを撃ち合うと、両側の NAT に相手へ向けた穴が開いて、直結が成立します。これをホールパンチングと呼びます。たいてい最初の1発は相手の NAT に捨てられますが、その1発が自分の側の穴を開けるので、反対側からの1発が通るようになるのです。
ところが、この穴あけが通らない NAT があります。代表がシンメトリック NAT です。シンメトリック NAT は、同じ端末の同じポートからでも、送る相手が変わるたびに別の外側ポートを割り当てます。すると、STUN サーバとの通信で知った番号(STUN 用の穴)と、相手へ撃ったときに実際に開いた番号がずれてしまい、相手はいつまでも外れた番号を狙うことになります。携帯回線の NAT や企業の NAT、厳しいファイアウォールで UDP 自体が止められている環境でも直結はできません。
その保険が TURN(Traversal Using Relays around NAT)で、開き直って「中継サーバ経由で転送する」仕組みです。どちらの NAT も「内側から TURN サーバへ出ていく通信」なら通すので、確実につながります。P2P の利点(最短経路・中継費用ゼロ)は失われます。そして全体の指揮をとるのが ICE(Interactive Connectivity Establishment)です。内側のアドレス(host)、STUN で得たアドレス(server reflexive)、TURN の中継アドレス(relay)という複数の「経路候補」を集め、優先度の高い組み合わせから順に疎通を確かめて、つながる中で最良の経路を選びます。実際のサービスでも、環境によっては少なくない割合の接続が TURN の中継に落ちるため、TURN サーバを用意しておくことは WebRTC の運用の定番の費用です。
NAT の種類を切り替えながら、実際に穴をあけて確かめてください。STUN に聞いたあと、片方の「相手へ撃つ」を相手の NAT へ運び、反対側からも撃つと、変換テーブルの行(穴)どうしが向かい合って直結します。片方をシンメトリックにすると、穴がずれる様子が表に出ます。
2台のブラウザが、それぞれ別の NAT の内側にいます。まず「STUN に聞く」を押して、2台が「外から見た自分の住所」を知るところから始めましょう。
シグナリングは仕様の外 — WebSocket の出番
もう1つ意外な設計が、「最初の待ち合わせの方法を WebRTC は決めていない」ことです。P2P を張るには、互いの経路候補や対応するコーデックといった情報(SDP と呼ばれる自己紹介文)を前もって交換する必要がありますが、まだつながっていない相手にどうやって渡すのか。この交換をシグナリングと呼び、WebRTC はその手段をアプリに任せました。既存の仕組みを自由に使えるようにするための割り切りで、実際にはシグナリング用のサーバを立てて WebSocket で中継するのが定番です。
候補を全部集め終わるのを待たず、見つかったものから順に送る方式(Trickle ICE)が一般的で、これにより接続までの時間が短くなります。確立した後はシグナリングサーバの役目は終わり、映像も音声もデータも端末の間を直接流れます。
暗号化は「任意」ではなく「必須」
WebRTC には平文のモードがありません。メディアは SRTP(Secure RTP)で、データは DTLS(TLS の UDP 版)で必ず暗号化され、鍵の交換も DTLS のハンドシェイクで行われます。カメラやマイクを使う API(getUserMedia)も、HTTPS で配信されたページからしか呼べません。Web で使われる HTTPS が「推奨から必須へ」と時間をかけて移行したのに対し、WebRTC は最初から「暗号化なしの選択肢を仕様上つくらない」設計を採りました。P2P ではどんなネットワークが間に挟まるか制御できないので、この割り切りは合理的です。
メディアと DataChannel
WebRTC が運べるのは音声・映像だけではありません。カメラやマイクの映像・音声を運ぶ MediaStream とは別に、DataChannel という、任意のバイナリやテキストを P2P で送れる汎用の通信路があります。信頼性(再送するかどうか)と順序の保証を用途に応じて緩められるのが特徴で、「多少落ちてもいいから最新の値を速く」というゲームの位置の同期も、「確実に全部届ける」ファイル転送も、同じ API で書けます。
なお、多人数のビデオ会議で全員と P2P を張ると、自分の映像を人数分アップロードすることになって破綻します。そのため実際のサービスは、各参加者の映像を選んで転送する中継サーバ(SFU)を挟む構成が主流です。それでも端末と SFU の間の通信そのものは WebRTC で行われており、「1対1は純粋な P2P、多人数は WebRTC を使った中継」という使い分けがいまの実務の標準形です。
試問
2台のブラウザ A・B が、それぞれ別の NAT(家庭や会社のルーターの住所の付け替え装置)の内側にいます。「STUN に聞く」で外から見た自分の住所を知り、「相手へ撃つ」をつかんで相手の NAT へ運ぶと、自分の NAT に穴(変換テーブルの行)が開きます。A の NAT は、送る相手ごとに新しいポートを割り当てるシンメトリック型に固定されていて、B の NAT の型は上の欄で選べます。
2台のブラウザが、それぞれ別の NAT の内側にいます。まず「STUN に聞く」を押して、2台が「外から見た自分の住所」を知るところから始めましょう。
