Networking 如何通过upnp编程实现双NAT端口转发

Networking 如何通过upnp编程实现双NAT端口转发,networking,routing,nat,upnp,portforwarding,Networking,Routing,Nat,Upnp,Portforwarding,我正试图通过UPNP实现双NAT。我的电脑连接如下: 互联网->路由器1->路由器2->电脑 我已在路由器2上成功完成端口转发,但无法在路由器1上完成。由于这些原因,来自服务器(位于Internet上)的数据包无法到达PC。 阅读了一些关于如何处理的文档,但大部分都找到了手动方式,如桥接网络或连接局域网 我在寻找使用UPNP协议在两个路由器上进行端口转发的递归解决方案。我猜torrent、skype也会这样做。 如何获取与路由器1相关的网络接口,然后在该网络上进行端口转发? 任何帮助都将不胜感激

我正试图通过UPNP实现双NAT。我的电脑连接如下:
互联网->路由器1->路由器2->电脑
我已在路由器2上成功完成端口转发,但无法在路由器1上完成。由于这些原因,来自服务器(位于Internet上)的数据包无法到达PC。
阅读了一些关于如何处理的文档,但大部分都找到了手动方式,如桥接网络或连接局域网
我在寻找使用UPNP协议在两个路由器上进行端口转发的递归解决方案。我猜torrent、skype也会这样做。
如何获取与路由器1相关的网络接口,然后在该网络上进行端口转发?

任何帮助都将不胜感激

谢谢,
Pawan

有一个解决类似问题的方法,尽管它假设“路由器1”上支持PCP,而不是UPnP。因此,让我们试着从纯理论的角度来处理这个问题,使用两个普通的UPnP路由器/NAT设备

UPnP通信有几个不同的步骤,如下所示:

  • 寻址
  • 发现
  • 描述
  • 控制
  • 事件
  • 介绍
寻址对我们来说没有什么意义,让我们假设每个地方都有合适的DHCP,并完成它。在我们的案例中,事件和演示几乎是无用的。因此,需要关注的主要事情是发现、描述和控制

发现通过SSDP消息交换工作。SSDP使用UDP进行传输,端口号为1900(默认情况下)和众所周知的多播地址

描述从设备在发现阶段提供的URL开始,控制点(在我们的例子中是PC)需要在此URL上发出HTTP GET请求,这意味着它使用TCP作为具有设备IP地址的传输协议(单播)

控件以设备在其描述中提供的URL开始,并在TCP之上的HTTP之上使用SOAP,而TCP对我们来说也意味着单播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地址。不幸的是,没有简单的标准方法可以做到这一点,但您至少有两种选择:跟踪路由(以您想要的任何方式)和强制IP扫描(最有可能的是,路由器1的潜在IP集是有限的)

现在,您可以与路由器1通信,但在与它通信时,还有一件小事情您应该始终记住——在任何内部UPnP消息中,您应该使用路由器2的IP地址(从路由器1侧看)及其端口。与路由器1上的
AddPortMapping
操作的
NewInternalClient
参数类似,您应该使用路由器2 IP。顺便说一句,这提出了一个路由器2 IP的问题,但您可以通过路由器2 UPnP
ExternalIPAddress
变量(此服务为)获得该问题

因此,总结一下:

  • 从技术上讲,这是可以做到的,尽管我怀疑任何标准库都不会为您做到这一点
  • 您需要的两件事是:
    • 路由器2“外部”IP,您可以通过
      ExternalIPAddress
      WANIPConnection的变量
      UPnP服务获得该IP
    • 路由器1“内部”IP(来自路由器2侧),需要跟踪路由或扫描
  • 给定路由器1IP,您只需要在发现步骤使用单播消息传递,而不是多播
  • 其他一切都应该正常工作,只需注意在UPnP消息中使用路由器2“外部”IP而不是PCs IP
通过使用,我已经能够实现双NAT端口转发

对于我的示例,假设我希望将端口6667转发到我的机器192.168.50.123,在双NAT后面。NAT的第一层IP范围为192.168.1.1-255,第二层IP范围为192.168.50.1-255

在第二层NAT内的机器上,只需像正常情况一样使用upnpc设置端口转发

$ upnpc -a 192.168.50.123 6667 6667 tcp
...
$ upnpc -l   # this will confirm the rule is in place
...
现在是稍微棘手的部分。我现在向外层NAT发出UPNP请求。由于通常的SSDP发现无法工作,我必须指定XML根描述URL
$ upnpc -u "http://192.168.1.1:5000/rootDesc.xml" -a 192.168.1.XX 6667 6667 tcp
...
$ upnpc -u "http://192.168.1.1:5000/rootDesc.xml" -l   # this will confirm the rule is in place
...
<INTERNET> -->  MY_PUBLIC_IP -> 192.168.1.XX -> 192.168.50.123