LinSoap

LinSoap

Null
github
x

使用JSによってWebRTCを介してlibp2pネットワークを作成し、相互に接続する(理論)

最近、OrbitDB という面白いデータベースプロジェクトを見つけました。分散型の公共アニメメタデータベースを作りたいと思っていますが、その分散化の実現方法は libp2p を使用しています。開発の過程で最も理解と設定が難しいのは、libp2p に関連する内容ですが、幸いにも公式が非常に質の高い入門チュートリアルを更新してくれましたので、関連する知識をたくさん学ぶことができました。内容をまとめるためにブログ記事を書く価値があります。
WebRTC with js-libp2p

WebRTC を選ぶ理由#

WebRTC とは#

WebRTC(Web Real-Time Communication)は、ウェブブラウザでリアルタイムの音声通話やビデオ通話を行うための API を提供する技術です。WebRTC を使用すると、ブラウザ間で直接 P2P 接続を確立し、データの送受信を行うことができます。現在の主要なブラウザはすべて WebRTC プロトコルをサポートしており、js-libp2p と組み合わせることで、ブラウザを libp2p ネットワークのノードとして直接参加させることができます。

libp2p ネットワークのトポロジー

JS-libp2p の接続性と能力#

libp2p にはさまざまな言語での実装がありますが、各実装の進捗状況と制限事項は公式ウェブサイトで提供されています。
libp2p の実装状況

各言語の実装状況
ブラウザの制限により、ブラウザは直接 TCP や QUIC プロトコルを使用して通信することはできません。ブラウザで独立した libp2p ノードを作成するためには、現時点では WebSocket、WebTransport、WebRTC の 3 つのプロトコルから選択することができます。また、公式ウェブサイトでは、libp2p の各プロトコル間の接続性の結果と、なぜブラウザが TCP や QUIC プロトコルをサポートしていないのかについても説明しています。
libp2p の各プロトコル間の接続性

ブラウザの制限事項

ブラウザ間の接続性
公式ウェブサイトで提供されている接続性の結果から、現時点では WebSocket と WebTransport はサーバーへの接続のみをサポートし、ブラウザへの接続はサポートしていません。現時点でのすべての実装の中で、js-libp2p と WebRTC を組み合わせることで、ブラウザを独立したノードとして扱うことができます。

WebRTC の制限と解決策#

P2P 接続を行う際に最も重要な問題は、2 つのブラウザがお互いを見つける方法であり、ノードが後続の接続を行うことができるようにすることです。そのために、STUN サーバーと TURN サーバーの 2 つの解決策が提供されています。

  • STUN サーバー:ネットワークには多くの NAT 構造が存在するため、ブラウザが相手を直接グローバル IP アドレスで見つけることは困難です。STUN サーバーは、ブラウザがお互いのノードを見つけ、相互に接続するためのサーバーです。多くの無料の公共 STUN サーバーが利用できます。
    無料の STUN 公共サーバー
  • TURN(リレー)サーバー:ブラウザ間で直接 P2P 接続を確立することができない場合、つまり STUN サービスによってノードが相互に見つかったが接続できない場合、TURN サーバーを使用して P2P 接続のすべてのトラフィックを中継することができます。そのため、TURN の使用コストが高く、良い選択肢ではありません。

ブラウザで P2P 接続を行う際には、相互にいくつかのメタデータ情報や対話記述情報を送信する必要があります。これはシグナリング(Signaling)交換と呼ばれます。WebRTC の標準では、これらの内容は強制的に規定されていません。開発者は自分でシグナリング交換の方法を実装する必要があります。
libp2p では、これらの 2 つの問題を解決するための新しいアプローチが設計されています。libp2p リレーノードを使用して解決します。libp2p リレーノードは、ネットワーク内で 2 つの役割を果たします。

  • Circuit Relay V2:ブラウザノードが直接 P2P 接続を確立できない場合、TURN サービスのコストが高すぎるため、Circuit Relay V2 がこの問題をうまく解決できます。なぜなら、Circuit Relay V2 は分散型であり、ネットワーク内のアクティブなノードがブラウザ間の相互発見を助け、P2P 接続ができない場合に必要なトラフィックを中継するからです。
  • PubSub Peer Discovery:上記の内容はノード間の接続性の問題を解決しますが、PubSub Peer Discovery はノード間の自動的な相互接続の問題を解決します。GossipSub モードは PubSub Peer Discovery の実装方法の 1 つであり、ノードは特定のトピックを購読し、新しいノードが参加し、同じトピックを購読した場合、PubSub Peer Discovery はすべてのトピックを購読しているノードに新しいノードのアドレスをブロードキャストします。各ノードはアドレスを受け取った後、接続を試みます。ただし、大規模なネットワークでは、ブロードキャストは非常にリソースを消費する行為であり、適切に使用しないと信頼性が失われる可能性があるため、このアプローチは本番環境では適していないかもしれません。

接続プロセス#

2 つのノードが P2P 接続を作成する方法、および libp2p リレーノードが接続中にどのような役割を果たすかについて、公式ドキュメントには大まかなワークフローを示すフローチャートがあります。

接続のフローチャート
このフローチャートについて、大まかなアイデアは、2 つのノードが接続を確立する際には、まずリレーノードのアドレスを知る必要があります。リレーノードに対して WebSocket 接続を確立し、2 つのノードがリレーノードと安定した接続を確立し、GossipSub と同じトピックを購読した後、リレーノードは Circuit Relay V2 を介して同じトピックを購読しているノードに対して相手のマルチアドレス(multiaddr)を通知します。マルチアドレスは以下のような形式です。

//ノードのマルチアドレス
//WebSocketポート9001を使用し、WebRTCをサポート
/ip4/127.0.0.1/tcp/9001/ws/p2p/12D3KooWDpJEwVdPBrQf6ZcwRYPzynBU2PZNGTQs3X8uh6FpxRTZ/p2p-circuit/webrtc/p2p/12D3KooWR3oBwBzZxSTd5RTKGJC2WsCxqWumpBUP1WjsixjeMQ9s
//WebSocketポート9002を使用せず、WebRTCをサポート
/ip4/127.0.0.1/tcp/9002/p2p/12D3KooWDpJEwVdPBrQf6ZcwRYPzynBU2PZNGTQs3X8uh6FpxRTZ/p2p-circuit/webrtc/p2p/12D3KooWR3oBwBzZxSTd5RTKGJC2WsCxqWumpBUP1WjsixjeMQ9s
//WebSocketポート9001を使用し、WebRTCをサポートしない
/ip4/127.0.0.1/tcp/9001/ws/p2p/12D3KooWDpJEwVdPBrQf6ZcwRYPzynBU2PZNGTQs3X8uh6FpxRTZ/p2p-circuit/p2p/12D3KooWR3oBwBzZxSTd5RTKGJC2WsCxqWumpBUP1WjsixjeMQ9s
//WebSocketポート9002を使用せず、WebRTCをサポートしない
/ip4/127.0.0.1/tcp/9002/p2p/12D3KooWDpJEwVdPBrQf6ZcwRYPzynBU2PZNGTQs3X8uh6FpxRTZ/p2p-circuit/p2p/12D3KooWR3oBwBzZxSTd5RTKGJC2WsCxqWumpBUP1WjsixjeMQ9s

最後に、2 つのノードはマルチアドレスを使用して WebRTC 接続を試み、P2P 接続を完了させます。

公式ドキュメントでは、より詳細な WebRTC 接続のワークフローも提供されています。

詳細な接続のフローチャート
libp2p リレーノードを相互に発見した後、WebRTC 接続を確立するための手順が記載されています。まず、各ノードは STUN サーバーから自身のパブリック IP とポートを取得します。次に、接続を開始するノードは、STUN からの情報に基づいて RTCPeerConnection オブジェクト(WebRTC 接続の状態を管理するオブジェクト)を作成し、DataChannel と SDP(セッション記述プロトコル、対話情報を記述するためのもの)を作成して接続の準備をします。接続を開始する側は、libp2p で定義されたシグナリング(webrtc-singnaling)を作成し、libp2p リレーノードを介して SDP を接続先に送信します。接続先が SDP を受け取った後、同様に RTCPeerConnection と SDP を作成し、送信元に応答として返信します。送信元は SDP を受け取り、記録します。これにより、2 つのノードはハンドシェイクを行い、SDP 情報を交換します。その後、ICE(P2P 接続で最適な接続パスを見つけるためのもの)を使用して相手ノードを RTCPeerConnection に追加します。最後に、ノイズ(暗号化通信プロトコル)を使用して接続チャネルを暗号化し、接続を完了させます。

以上で、libp2p におけるブラウザノードの直接接続を WebRTC を使用してどのように解決するかについて、大まかな理解ができました。これには以前に理解していなかった用語が多く含まれているため、矛盾や誤りが生じる可能性があります。公式の情報を参考にしてください。

WebRTC with js-libp2p
libp2p Connectivity
Peers - libp2p
SDP - MDN Web
mutiaddr - libp2p
WebRTC - MDN Web
Circuit Relay - libp2p
lib2p2 signaling-protocol -Github
js-libp2p-pubsub-peer-discovery -Github

以上が翻訳されたテキストです。

読み込み中...
文章は、創作者によって署名され、ブロックチェーンに安全に保存されています。