有一个IGD-PCP IWF 规范试图解决类似的问题,尽管它假设您的“路由器 1”支持 PCP,而不是 UPnP。因此,让我们尝试从纯理论的角度使用两个普通的 UPnP 路由器/NAT 设备来解决这个问题。
根据UPnP 设备架构 2.0 版,UPnP 通信有几个不同的步骤:
寻址对我们来说没什么兴趣,让我们假设到处都有正确的 DHCP 并完成它。在我们的案例中,事件和演示也几乎没有用。所以主要关注的是发现、描述和控制。
发现通过 SSDP 消息交换工作。SSDP 使用 UDP 进行传输,端口号为 1900(默认情况下)和众所周知的多播地址。
描述从设备在发现阶段提供的 URL 开始,控制点(在我们的例子中是 PC)需要在这个 URL 上发出 HTTP GET 请求,这意味着它使用 TCP 作为具有设备 IP 地址的传输协议(单播) .
控制从设备在其描述中提供的 URL 开始,它在 TCP 之上的 HTTP 之上使用 SOAP,这反过来对我们来说也意味着单播 IP。
因此,所有这些对于双 NAT 意味着,在 UPnP 交互的描述和控制步骤中,我们从 PC 到路由器 1 的通信是零问题,因为所有这些只是具有单播 IP 地址的标准 TCP。但是要进入描述步骤,我们需要有一个路由器 1 的 URL,所以让我们仔细看看这个 URL 是如何以正常方式获取的。
有两种主要的发现机制——广告(当设备周期性地多播一些关于它的信息时)和搜索(当控制点发送多播搜索消息并且设备用单播响应来响应时)。显然,默认情况下,我们在路由器 2 后面的 PC 无法从路由器 1 获得多播广告,而路由器 1 也无法从 PC 获得多播搜索消息,所以我们这里有一个问题,现在的问题是是否有可能没有多播的通信。
幸运的是,相同的架构文档说:
此外,允许控制点将发现消息单播到端口 1900 上的特定 IP 地址或可选 SEARCHPORT.UPNP.ORG 标头字段(其取代端口 1900 用于此用途)指定的端口上,搜索 UPnP该特定 IP 地址的设备或服务。
...
所有设备都应在端口 1900 或 SEARCHPORT.UPNP.ORG 标头字段中指定的端口号(如果提供)上侦听传入的单播搜索消息,并且如果它们的任何根设备、嵌入式设备或服务与发现消息。
这意味着如果您知道路由器 1 的 IP 地址(当然是从路由器 2 端),您可以(最重要的是,规范允许)通过单播 UDP 消息与它通信,这也是 NAT 友好的,所以不是从路由器 2 后面的 PC 完成的问题。
唯一剩下的就是获取路由器 1 的 IP 地址。不幸的是,没有简单的标准方法可以做到这一点,但您至少有两个选择:跟踪路由(以您想要的任何方式)和暴力 IP 扫描(很可能,路由器 1 的潜在 IP 集是有限的)。
现在您可以与路由器 1 进行通信,但在与路由器 1 通信时,您仍应始终记住一件小事——在任何内部 UPnP 消息中,您应该使用路由器 2 的 IP 地址(从路由器 1 一侧看到)及其端口。就像路由器 1 上NewInternalClient
的操作参数一样,AddPortMapping
您应该使用路由器 2 IP。顺便说一句,这引发了路由器 2 IP 的问题,但您可以通过路由器 2 UPnP服务ExternalIPAddress
变量获得该问题(IGD 需要此服务才能实现)。WANIPConnection
所以,总结一下:
- 这在技术上是可以做到的,尽管我怀疑任何标准库都会为你做到这一点
- 你需要的两件事是:
- 路由器 2“外部”IP,您可以通过UPnP 服务
ExternalIPAddress
的变量获得该 IPWANIPConnection
- 需要跟踪路由或扫描的路由器 1“内部”IP(来自路由器 2 端)
- 给定路由器 1 IP,您只需要在发现步骤使用单播消息而不是多播
- 其他一切都应该正常工作,只需要注意在 UPnP 消息中使用路由器 2“外部”IP 而不是 PC IP