如何通过upnp以编程方式实现双NAT端口转发

时间:2013-09-18 06:49:40

标签: networking routing nat upnp portforwarding

我正在尝试使用UPNP实现双NAT。我的PC连接如下:
互联网 - >路由器1 - >路由器2-> PC
我已成功完成路由器2上的端口转发,但无法在路由器1上完成。由于来自服务器(在Internet上)的数据包无法到达PC。
通过很少的文件解决了如何解决但大多发现手动方式如桥接网络或局域网线。
我正在寻找使用UPNP协议在两个路由器上进行端口转发的一些递归解决方案。我猜洪流,Skype也是如此 如何获得与路由器1相关的网络接口,然后在该网络上进行端口转发?

任何帮助都将受到高度赞赏。

谢谢,
爬完

2 个答案:

答案 0 :(得分:0)

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

根据UPnP Device Architecture version 2.0,UPnP通信有几个不同的步骤

  • 寻址
  • 发现
  • 描述
  • 控制
  • 事件(eventing)
  • 介绍

寻址对我们来说没有什么意义,让我们假设在任何地方使用适当的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集合是有限的)。 / p>

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

所以,总结一下:

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

答案 1 :(得分:0)

使用 upnpc cli tool 我已经能够让双 NAT 端口转发工作。

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

在 NAT 2 层内的机器上,只需像平常一样使用 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。它通常是像 http://192.168.1.1:5000/rootDesc.xml 这样的标准,但在某些硬件上,端口号是随机的。我发现只是端口扫描网关地址最终会发现它。

现在我有了 rootDesc url http://192.168.1.1:5000/rootDesc.xml,然后我向外层 NAT 发出 UPNP 命令:

$ 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
...

使用 -u 选项而不是发现 rootDesc,它只使用提供的 URL。 地址 192.168.1.XX 应该是第 2 层网络的 IP 地址,如第 1 层网络所见。当运行第一组 UPNP 命令时,这将显示出来,因为从 NAT 的角度来看,它是“外部”地址。

有了现在的设置,流量会变成这样:

<INTERNET> -->  MY_PUBLIC_IP -> 192.168.1.XX -> 192.168.50.123