WebRTCでのP2P通信
WebRTC(Web Real-Time Communication)
WebRTC(Web Real-Time Communication)は、Webブラウザやモバイルアプリケーション間で、直接リアルタイムの音声、ビデオ、データ通信を可能にする技術で、SkypeやGoogle Meetのようなビデオ通話アプリケーションで広く使われています。
WebRTC自体はネットワークプロトコルではなく、異なるアプリケーション間でも共通のAPIや手順を用いてP2Pでのリアルタイム通信を実現する為のフレームワークです。
WebRTC APIに関しては、W3C(World Wide Web Consortium)によって標準仕様として策定されており、これによって異なるOS/ブラウザ間であっても互換性が確保されています。
また、WebRTCで使用する各所ネットワークプロトコルや関連する通信技術に関しては、IETF(Internet Engineering Task Force)によって標準化が行われています。
こうしたWebRTCを構成する技術の中で、最も重要な機能の一つが、NAT(Network Address Translation)を越えて、P2P通信の経路を確立する技術です。
P2P(Peer to Peer)通信
ウェブブラウジングやメール、その他のクラウドサービスなど、現在のインターネットサービスのほとんどが、サーバ・クライアント型の通信方式で提供されています。
サーバ・クライアント通信
これに対し、P2P(Peer to Peer)通信とは、サーバーを介さずに、個々のコンピュータ同士が直接接続し、データの送受信を行う方式です。
P2P通信
WebRTC(Web Realtime Cominication)では、サーバを介さずにP2P通信を用いることで、低遅延で効率的な映像/音声の送受信を可能にしています。
ただし、サーバ・クライアント通信と比べて、P2P通信では、最初の接続の確立が難しい面があります。
その最も大きな要因がNAT(Network Address Translation)です。
NAT(Network Address Translation)
インターネット上で相手との通信を確立する為には、接続する相手の場所(=グローバルIP)が必要です。
グローバルIPとは、インターネット上で一意に識別されるIPアドレスのことを指します。インターネットに接続するデバイスが、他のネットワークやデバイスと通信するために、世界中でユニークなアドレスを持つ必要があります。このようなユニークなアドレスがグローバルIPアドレスです。
サーバ・クライアント通信の場合、接続先のサーバのグローバルIPアドレスは、多くの場合、ドメイン名という形で文字列として公開され、DNS(Domain Name System)サーバでグローバルIPに変換されます。
これに対し、一般家庭や社内LANなどでは、そのローカルネットワーク(LAN)内で自由に設定が可能なIPアドレス(プライベートIP)が使用されます。
このプライベートIPは、LAN内では自由に利用できますが、インターネット上では利用できません。
その為、ローカルネットワーク内で使用されるプライベートIPを、インターネット接続可能なグローバルIPに変換する技術が必要になります。
特に、IPv4では、グローバルIPアドレスの枯渇が懸念されており、1つのグローバルIPを複数のプライベートIPで共有して使用する為の技術として、NAT(Network Address Translation)が利用されています。
NATを介したインターネットとの通信手順
一般的な家庭では、インターネットに接続する為に、インターネットサービスプロバイダー(ISP)と契約して、グローバルIPを一つ、割り当てられます。この割り当てられたグローバルIPを使って、家庭内の複数のプライベートIPを設定した端末がNATを介してインターネットと通信することになります。
NATには様々な種類がありますが、ここでは最も単純なフルコーンNATの場合を例に、プライベートIPを設定したPCが、インターネット上のサーバと通信する流れを見ていきます。
家庭内のPCがルータのNAT機能を使って、サーバと通信する例
ルータには、家庭内のローカルネットワークと、外部のインターネットを接続する為に、2つのIPアドレスが設定されています。
一つは家庭内ネットワーク上のプライベートIPアドレス(192.168.1.1)、もう一つは、プロバイダーから割り振られたグローバルIPアドレス(12.34.56.78)です。
まず、家庭内のPCからサーバに対して通信を行う場合、ルータに対してその通信が送られます。
通信を受信したルータでは、PCからの通信を、インターネット上のサーバに転送します。その際、サーバ側からの返信をPCに通す為に、ポート番号(ここでは100番)を割り当てて、「グローバルIP側のポート100番への通信=192.168.1.5へ通す」というマッピングを作成します。
ルータから転送された通信を受信したサーバは、送信元のルータのポート番号100番に対して返信します。
このサーバからの返信を受信したルータは、「グローバルIP側のポート100番への通信=192.168.1.5へ通す」というマッピングが行われているので、192.168.1.5に通信を転送し、家庭内のPCがそれを受信する、という流れになります。
P2P通信とNAT
このように、NATのマッピングは、家庭内の端末からの通信をトリガーにして自動的に行われます。また、一度設定されたマッピング情報は、時間が経つと消えてしまう為、外部から家庭内のPCに直接通信しようとしても、NATのマッピングが存在していない状態では、外部からの通信はルータで遮断され、家庭内のセキュリティが保たれることになります。
しかし、WebRTCのようなP2P通信を行う場合は、このNAT機能が大きな壁となって、通信経路の確立を難しくしています。
WebRTCでは、このNATを越えるために、いくつかの手段を駆使して、P2P通信経路の確立を試みます。
WebRTCでのNAT越えの方法
WebRTCではP2P通信の接続を確立する為に2つの外部サーバを使用してNAT越えを試みます。
STUN(Session Traversal Utilities for NAT)サーバ
STUN(Session Traversal Utilities for NAT)は、NATを超えて、インターネット上でP2P通信を確立するために使われるプロトコルです。
NAT配下に存在する端末が、自分の通信がインターネットに出る際にマッピングされる、グローバルIPアドレスとポート番号を知るために使用されます。
下図は前章で説明したNAT配下のPCがインターネット上のサーバに接続する際の構成で、STUNサーバを利用した場合の概念図です。
NAT配下の端末からSTUNサーバに対してリクエストが投げられると、STUNサーバ側は、NATでマッピングされたグローバルIPとポート番号を返却します。
これによって、NAT配下の端末では、自分がインターネットからの通信を受信する際に使用されるNAT上でのマッピング情報(グローバルIPとポート番号)を知ることが可能になります。
こうして得た自分のグローバルIPとポート番号をP2P通信の相手に伝え、また、相手のグローバルIPとポート番号も教えてもらうことで、P2P通信が確立されます。
ちなみに、このSTUNは非常に軽量なプロトコルで、サーバの処理負荷も低いため、無償で公開しているサーバが数多くあります。
TURN(Traversal Using Relays around NAT)サーバ
TURN(Traversal Using Relays around NAT)は、NATやファイアウォールを越えてP2P通信の接続を確立する為に、通信の仲介を行うプロトコルです。
P2P通信はクライアント同士が直接データを送受信しますが、NATやファイアウォールの制限が厳しい場合、直接の接続ができないことがあります。このような場合に、TURNサーバーが中継サーバーとして機能し、クライアント間のデータ通信をサーバー経由で行います。
上図を見ると分かりますが、TURNサーバへの接続は、通常のインターネット上のサーバへの接続と同じなので、両方の端末が問題なく接続できます。そのうえで、それぞれの端末からの映像や音声をTURNサーバが中継役となって送受信を行う形です。
この形式は、サーバ・クライアント通信です。
当然、遅延が大きくなりますし、サーバの処理負荷が非常に高くなり、維持コストもかかることになります。
その為、WebRTCでは、まずは可能な限りSTUNによる直接P2P接続の確立を優先し、TURNはあくまでバックアップの手段として使用されるのが一般的です。
P2P接続までの流れ
STUNやTURNを利用して、P2P通信可能な最適なネットワーク経路を選択する為の仕組みを、ICE(Interactive Connectivity Establishment)と呼びます。
このICEを使用して、WebRTCでP2P通信を確立する手順を説明します。
ICEによるP2Pセッション確立までの流れ
1. ICE(Interactive Connectivity Establishment)候補の収集
まずは、自分が属するネットワーク経路の候補を、STUN/TURNを使用しながら収集します。
この経路情報には、主に次の3種類の候補が含まれます。
- 自身のプライベートIPアドレス(ローカルIPアドレス)
- STUNサーバを使って取得したグローバルIPアドレス
- TURNサーバを介した中継経路
2. 収集したICE候補情報の交換
収集したICE候補情報を、接続相手の端末と交換します。
ICE候補情報は、SDP(Session Description Protocol)の形式で記載され、交換されます。
SDPは、経路情報だけでなく、送信されるメディアの種類(ビデオ、音声、データなど)や、使用するコーデックなどの情報も記載されたテキスト情報です。
v=0
o=- 123456 654321 IN IP4 xxx.xxx.xxx.xxx
s=Example Session
c=IN IP4 xxx.xxx.xxx.xxx
t=0 0
m=audio 49170 RTP/AVP 0
a=rtpmap:0 PCMU/8000
m=video 51372 RTP/AVP 31
a=rtpmap:31 H261/90000
この情報交換(シグナリングと呼ばれます)のプロトコルに関しては、WebRTCとしては特に定義がなく、どのように実現するかはアプリケーションに任されています。
一般的にはWebSocket等を使用しますが、極端な話、メールでも構いません。(リアルタイム性が落ちますが。。。)
3. ICE接続確立
ICE候補情報を交換したら、それぞれの候補を使用して、STUNサーバを利用しながら、最も効率的で安定した経路を選定します。
直接接続ができない場合は、TURNサーバを介してリレー接続を行います。
4. セッションの確立
最適なICE候補が選ばれたら、実際にP2Pでのリアルタイムセッションが確立され、映像や音声が送信されます。
Vanilla ICEとTrickle ICE
収集したICE候補の交換方法には、2種類の方法が存在します。
Vanilla ICE
Vanilla ICEとは、ICE候補の収集が終了してから、SDPを交換する方法です。
すべてのICE候補の収集が終了するまで交換が行われないため、時間がかかることがありますが、その反面、すべての情報が一つのSDPに含まれている為、交換処理も1回ずつ行えばよく、処理としてはシンプルになります。
Trickle ICE
Trickle ICEとは、ICE候補を収集する際、収集できたICE候補情報を非同期で相手に渡す方法です。
Trickle ICEの場合、最初の交換では、メディア情報のみを記載したSDP情報を交換します。
その後、ICE候補が収集されるたびに相手に送信し、経路が確立できた時点で、P2Pセッションを開始する、というやり方です。
この方法だと、すべてのICE候補の収集が終了するまで待つ必要がなく、接続が確立できた時点でP2Pセッションを開始することが可能になり、接続までの時間を短縮できる可能性があります。
ただし、非同期で送信されてくるICE候補情報を受信して処理を行う必要がある為、Vanilla ICEと比較すると、実装は複雑になります。
Discussion