即使对等点可以互相发送 UDP 数据包,WebRTC 也无法连接 P2P

Att*_*nen 9 javascript p2p nat stun webrtc

我的印象是,尽管有 NAT,WebRTC 仍竭尽全力实现 P2P 连接。[1][2] 这就是为什么我惊讶地发现 WebRTC 在某些很容易实现 P2P 连接的情况下无法连接对等点。我想了解为什么会发生这种情况,以及我是否可以采取任何措施来改善这种情况。


为什么我说P2P在某些情况下很容易实现呢?我之所以这么说是因为我在不同网络上的两台设备上进行了实验:

  • 设备 F 连接到全锥 NAT 后面的互联网
  • 设备 S 通过对称 NAT 连接到互联网

我可以通过以下方式轻松实现这些设备之间的 P2P 连接:

  1. 设备 F 将连接绑定到随机(不可预测)端口,并通过该端口将 UDP 数据包发送到 Internet 上的任何位置。由于 F 位于全锥 NAT 后面,因此该数据包已“打孔”打开的端口,允许任何外部地址现在通过该端口发送数据包。就我而言,我在本地打开的端口似乎与外部端口相同。(如果外部端口与本地端口不同,我们可以使用 STUN 之类的东西来找出外部端口。)

  2. 设备 S 将连接绑定到随机(不可预测)端口,并通过该端口向设备 F 的外部 IP 和端口发送 UDP 数据包。该数据包可以传送,因为该端口在步骤 1 中已打洞打开。之后数据包时,设备 S 通过自己的端口打洞,允许来自设备 F 的数据包通过它发回。设备F会知道将数据包发送到哪里,因为S发送的数据包包含外部IP和端口。由于设备 S 具有对称 NAT,打洞不会为所有流量打开端口,仅针对来自设备 F 的流量(设备 F 的外部 IP 和端口)。

我使用 Python 来验证我是否能够在这些设备之间打开 P2P 连接并双向发送消息,如上所述。我不明白为什么WebRTC无法实现这样的P2P连接。


为什么我声称 WebRTC 在某些应该很容易连接的情况下无法连接?我之所以这么说是因为我尝试使用 3 个不同的代码示例来实现 WebRTC P2P 连接。当设备位于同一本地网络时,所有示例均有效,但当设备位于不同网络时,所有示例均无效(上述设置)。我尝试过的库都没有提供任何有用的调试信息来找出问题所在,并且 chrome://webrtc-internals 也没有提供任何有用的信息。我还尝试在 Firefox 中验证此问题不是特定于实现的。

具体来说,我尝试了以下代码示例:

  1. simple-peer,一个 WebRTC 库。我尝试了自述文件中的第一个示例代码。

  2. PeerJS,另一个 WebRTC 库。我尝试了他们设置的演示页面。

  3. Stackoverflow 答案中的代码片段。[3]

在所有 3 个实验中,我还尝试切换哪个设备发起连接以及哪个设备接收连接。

由于这个问题并不特定于 WebRTC 实现,也不特定于任何特定的 WebRTC JavaScript 库,因此我开始怀疑 WebRTC 的规范在某些基本方面被破坏,从而阻止了 WebRTC 在某些情况下实现 P2P 连接他们很容易实现。我在这里错过了什么吗?

[1] https://webrtc.org/getting-started/turn-server指出:“对于大多数 WebRTC 应用程序来说,需要服务器来中继对等点之间的流量,因为客户端之间通常不可能使用直接套接字”。这给人的感觉是WebRTC应该能够在很容易实现的场景下实现P2P连接。

[2] https://webrtcforthecurious.com/docs/03-connecting/声明:“WebRTC 将收集它能收集的所有信息,并将竭尽全力实现两个 WebRTC 代理之间的双向通信。” 这也给人的印象是WebRTC应该能够在很容易实现的场景下实现P2P连接。

[3]具有手动信令的 WebRTC 数据通道,请举例?