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

标签 networking routing nat upnp portforwarding

我正在尝试使用UPNP实现双NAT。我的电脑连接如下:
互联网->路由器1->路由器2-> PC
我已经在路由器2上成功完成了端口转发,但是在路由器1上却无法完成。由于来自服务器(位于Internet上)的数据包无法到达PC。
很少有文件介绍如何解决,但是主要找到了手动的方式,例如桥接网络或放置局域网。
我宁愿寻找一些使用UPNP协议(protocol)的递归解决方案,以在两个路由器上进行端口转发。我猜洪流,Skype也是一样。
如何获取与路由器1相关的网络接口(interface),然后在该网络上转发端口?
任何帮助将不胜感激。

谢谢,
帕万

最佳答案

尽管它假定您的“路由器1”(而不是UPnP)支持PCP,但有一个IGD-PCP IWF specification试图解决类似的问题。因此,让我们尝试使用两个简单的UPnP路由器/NAT设备从纯理论的角度来解决此问题。

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

  • 寻址
  • 发现
  • 说明
  • 控制
  • 事件
  • 演示文稿

  • 对我们而言,寻址没有什么意义,让我们在各处假设适当的DHCP并完成它。事件和演示在我们的案例中几乎也没有用。因此,主要要关注的是发现,描述和控制。

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

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

    控制以设备描述中提供的URL开头,它在HTTP之上的SOAP在TCP之上的SOAP上使用,这反过来又对我们意味着单播IP。

    因此,对于双NAT而言,所有这些意味着在UPnP交互的描述和控制步骤中,从PC到路由器1的通信几乎没有问题,因为所有这些都是带有单播IP地址的标准TCP。但是要进入描述步骤,我们需要有一个路由器1的URL,因此让我们仔细研究一下如何以正常方式获取此URL。

    发现的主要机制有两种:通告(当设备定期多播一些有关它的信息时)和搜索(当控制点发送多播搜索消息,并且设备使用单播响应对此消息做出响应时)。显然,默认情况下,我们在路由器2后面的PC无法从路由器1获取多播广告,而路由器1也无法从PC获取多播搜索消息,因此我们这里有一个问题,现在的问题是是否有可能没有多播的通信。

    幸运的是,同一体系结构文档中说:

    In addition, a control point is allowed to unicast a discovery message to a specific IP address on port 1900 or on the port specified by the optional SEARCHPORT.UPNP.ORG header field (which supersedes port 1900 for this use), searching for a UPnP device or service at that specific IP address.

    ...

    All devices shall listen to incoming unicast search messages on port 1900 or, if provided, the port number specified in the SEARCHPORT.UPNP.ORG header field and shall respond if any of their root devices, embedded devices or services matches the search criteria in the discovery message.



    这意味着如果您知道路由器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的问题,但您可以通过 ExternalIPAddress service的路由器2 UPnP WANIPConnection变量(此服务为required for IGDs to implement)来解决这个问题。

    因此,总结一下:
  • 从技术上讲可以做到,尽管我怀疑任何标准库都可以为您做到这一点
  • 您需要做的两件事是:
  • 路由器2“外部” IP,您可以通过ExternalIPAddress UPnP服务
  • WANIPConnection变量来获取
  • 路由器1“内部” IP(从路由器2端),需要跟踪路由或扫描
  • 给定路由器1 IP的
  • ,您只需要在发现步骤中使用单播消息传递即可,而不是多播
  • 其他所有内容都应该可以正常工作,只需要在UPnP消息中使用路由器2“外部” IP而不是PC IP告诫
  • 关于networking - 如何以编程方式通过upnp实现双NAT端口转发,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18865586/

    相关文章:

    networking - Docker 1.10 容器在局域网中的 IP

    ruby-on-rails - Vagrant 减慢对 Rails 服务器的 http 请求

    c++ - 如何克隆载体?

    asp.net - 如何从RouteData获取路线名称?

    udp - 选择 UDP 打洞的端口号

    android - 智能手机固件能否嗅探 Android 手机的传出 HTTP 请求?

    security - 多个防火墙 "/admin/login_check"找不到

    c# - ASP.NET MVC 2 中具有约束的可选路由参数?

    ruby-on-rails - 使用 VirtualBox 从访客访问主机上的站点?主机和访客都是linux

    nat - gethostbyaddr() 应该在 NAT 环境中工作吗?