P2P 应用程序,打孔不适用于与端点无关的映射 NAT

Posted

技术标签:

【中文标题】P2P 应用程序,打孔不适用于与端点无关的映射 NAT【英文标题】:P2P Application, hole punching not working fro endpoint independent mapping NATs 【发布时间】:2016-05-03 08:56:36 【问题描述】:

我目前正在使用“打孔”方法在 C 中实现 (UDP) p2p 应用程序。我发现真的说明了 J. Selbie 以前的帖子,他解释了基础知识 并相应地进行(post1,post2)但可能我遗漏了一些东西,只有一个对等方正在接收数据,而另一个没有。

这是我正在采取的步骤:

设置:其中一个对等体连接到 4G 蜂窝加密狗 (NAT A),另一个连接到连接到 ISP 提供商 (NAT B) 的路由器。 这些是两个 NAT 的 stunclient(特技客户端)报告的结果。

NAT A:
Binding test: success
Local address: X1:48383
Mapped address: Y1:28265
Behavior test: success
Nat behavior: Endpoint Independent Mapping
Filtering test: success
Nat filtering: Address and Port Dependent Filtering

NAT B:
Binding test: success
Local address: X2:49158
Mapped address: Y2:49158
Behavior test: success
Nat behavior: Endpoint Independent Mapping
Filtering test: success
Nat filtering: Address and Port Dependent Filtering

现在,根据这些结果,我的理解是,两个 NAT 都有合理的行为,打孔可能会成功(注意 NAT A 不做端口保留)。

打孔尝试: 两个客户端都通过 UDP 联系面向公众的服务器(STUN/集合点)以发现/交换 ip:port 对。当每个客户端收到来自服务器的响应时,它们会发送一个 UDP 数据报给另一个对等点(ip:port 被联系的公共服务器看到),然后继续发送更多信息并接收并回复该地址的消息它来自哪里。 我使用与公共服务器联系的同一套接字发送数据报,仅更改 sendto 函数上的目标 ip:port。

问题是,NAT A 后面的主机(连接到 4G 加密狗)总是会收到消息,尽管回复了正确的 ip 和目标端口,但后面的主机(NAT B)永远不会收到消息。有什么想法我在这里想念的吗?或者如何诊断问题??

提前致谢。

【问题讨论】:

【参考方案1】:

这是标准和一般场景,其中蜂窝和 wifi(ISP) 网络之间的 p2p(点对点)呼叫是不可能的。现在为什么?

为什么?:所有蜂窝网络都使用一种经济高效的方法,其中没有用户可以拥有专用的公共 IP 或 NAT。这意味着移动公共 IP 可能会在几个小时左右后发生变化。因此,蜂窝网络提供商可以为大量用户使用较少数量的公共 IP。这个过程通常是通过为每个请求分配新的 ip:port 来完成的,这是symmetric NAT 的一个特性。因此,在您的情况下,由于 NAT B 是 Nat filtering: Address and Port Dependent Filtering,这意味着如果来自 NAT A 的数据对于每个发送/请求都有唯一的 ip:port,那么 NAT B 将过滤数据并且调用将失败。

解决方案: 一般情况下,您需要一个托管在公共 IP 上的中继服务器,它将接收来自 A 的数据并将其转发给 B,并且 B 也将这样做而不进行任何过滤。这种服务器称为TURN server。

现在我不确定为什么您的 stuntman 测试客户端会同时检测 A 和 B 的 PRC NAT(Nat filtering: Address and Port Dependent Filtering)。对于 A,它必须是 Symmatric NAT,因为它在蜂窝网络上。

【讨论】:

以上是关于P2P 应用程序,打孔不适用于与端点无关的映射 NAT的主要内容,如果未能解决你的问题,请参考以下文章

UDP 打孔:PC 到 Android 的 UDP 连接不适用于非本地地址

UDP打孔混乱

为啥 p2p 的 nat 打孔需要服务器

使用 dht 可以代替 P2P 网络中使用信令服务器打孔吗?

APIUrl 前缀不适用于 Azure APIM

无法使用 STUN 执行 TCP 打孔