有一个IGD-PCP IWF specification试图解决类似的问题,虽然它假设你的"Router 1"支持PCP,而不是UPnP . 因此,让我们尝试从两个简单的UPnP路由器/ NAT设备的纯理论角度来解决这个问题 .

寻址

发现

说明

控制

事件

演示文稿

对我们来说,寻址并不重要,让我们假设在任何地方使用适当的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),搜索该特定IP地址的UPnP设备或服务 . ...所有设备应在端口1900上侦听传入的单播搜索消息,或者,如果提供,则在SEARCHPORT.UPNP.ORG头字段中指定端口号,并且如果它们的任何根设备,嵌入式设备或服务与搜索匹配,则应响应发现消息中的条件 .

这意味着如果你知道路由器1的IP地址(当然是来自路由器2的那个),你可以(最重要的是,规范允许)与单播UDP消息进行通信,这也是NAT友好的,所以不是路由器2后面的PC要做的问题 .

唯一剩下的就是获得路由器1的IP地址 . 不幸的是,没有简单的标准方法可以做到这一点,但你至少有两个选择:tracerouting(以你想要的任何方式)和暴力IP扫描(最有可能的是,路由器1的潜在IP集合是有限的) .

现在您可以与路由器1进行通信,但在与其通信时仍然应该记住一件小事 - 在任何内部UPnP消息中,您应该使用路由器2 IP地址(从路由器1侧看到)及其端口 . 与路由器1上的 AddPortMapping 参数的 NewInternalClient 参数一样,您应该使用路由器2 IP . 这个,BTW,提出了一个路由器2 IP的问题,但是你可以通过路由器2 UPnP ExternalIPAddress 变量WANIPConnection service获得(该服务是required for IGDs to implement) .

所以,总结一下:

技术上可以做到这一点,虽然我怀疑任何标准库都能为你做到这一点

你需要的两件事是:

路由器2 "external" IP,你通过 WANIPConnection 变量 WANIPConnection UPnP服务获得

路由器1 "internal" IP(来自路由器2侧),需要跟踪路由或扫描

给定路由器1 IP,您只需要在发现步骤而不是多播时使用单播消息传递

其他一切都应该正常工作,只需注意在UPnP消息中使用路由器2 "external" IP而不是PC IP