UPnP打孔不能使用外部IP访问本地子网上的设备

Posted

技术标签:

【中文标题】UPnP打孔不能使用外部IP访问本地子网上的设备【英文标题】:UPnP hole punching can't use external IP to access device on local subnet 【发布时间】:2020-05-22 13:32:04 【问题描述】:

我有一种特殊的情况,我需要能够为多节点对等类型的应用程序执行 NAT 打孔;其中所有节点必须从可公开访问的 IP 地址相互引用,即使其中一些节点可能位于本地子网上。

在这个问题 (UDP hole punching implementation) 的帮助下,我已经能够使用 Open.Nat 成功映射端口。

我的代码基本上就是这么简单:

var discoverer = new NatDiscoverer();
var device = await discoverer.DiscoverDeviceAsync();
await device.CreatePortMapAsync(new Mapping(Open.Nat.Protocol.Tcp, port, port));

这成功地在我的路由器中创建了一个地图

我现在可以通过执行以下操作成功地连接到此 IP 和端口号从外部网络(在移动数据连接上测试)

TcpClient client = new TcpClient();
client.Connect("publicip", 6968);

但是,当我尝试从 本地子网 连接到 相同的公共 IP 地址 时,连接将以“No connection could be made because the target machine actively refused it?”失败。

我已经使用wireshark查看是否有任何数据包到达目标机器,但似乎没有。

很明显,路由器可能无法在本地子网上正确转发/路由连接,所以我想了解的是,这是 UPnP 协议的已知限制还是特定于我的路由器?当您创建我错过的映射时,也许有一个技巧?

我注意到我的路由器似乎使用 MiniUPnP http://miniupnp.free.fr/ 版本 20160321

我知道这是一个很难回答的问题,但希望我们能从专家那里得到一些关于 UPnP 在这种情况下应该做什么的说明。

编辑:

关于我的问题的更多背景信息;让我详细说明为什么我有这样的要求。我在跨网络边界的移动设备上使用Akka.NET clusters,使用 Akka 集群要记住的关键点是 要成功获得 Akka.NET 集群以形成集群的所有成员必须是双向可达的彼此

现在考虑这样的情况

我的目标是只需为服务器节点分配一个静态 ip,并允许所有集群节点无缝地进出网络边界。实现这一点的理想方法是为网络上的每个节点分配可公开访问的地址,无论其物理位置如何。

【问题讨论】:

我不相信这有任何要求:路由器可以做它想做的事。也就是说,它在这里的行为确实不寻常。 @canton7 我应该有机会尽快用其他设备正确测试此行为,并将报告结果 我们的项目也有同样的要求,可能是防火墙之类的小东西,你试过禁用它吗? 等一下,我给了它一个更好的阅读,所以你正在尝试使用公共地址和 upnp 端口在同一个本地子网上连接......你为什么不直接连接直接地 ?那是在寻找 trubles,upnp 不是为此而生的,它在技术上可以工作,但这不是它的意思...... @L.Trabacchin 我提供了更多背景信息,说明我为什么在我的案例中采用这种方法。 【参考方案1】:

这不是您可以真正解决的问题,也不是 C# 所特有的。大多数路由器只会匹配到达其面向 Internet 的接口的 NAT 数据包。如果您希望允许在同一个 NAT 后面运行的多个节点直接相互连接,则需要实施另一种解决方案。

例如,您可以共享每个节点的私有接口地址。如果公共地址匹配,则尝试直接连接。

【讨论】:

最后,我采用了每个人的 cmets 并确定了一种方法,当节点位于本地子网上时,它们被赋予静态 IP 地址。感谢您的意见。

以上是关于UPnP打孔不能使用外部IP访问本地子网上的设备的主要内容,如果未能解决你的问题,请参考以下文章

如何访问 UPnP 设备的服务?

获取 UPnP 设备的 IP 地址

iPhone上的TCP打孔

子网掩码一般是多少

[VB.NET]Upnp/udp打孔聊天程序tcp/udp sockets

如何在集群外部通过ip直连Pod?