使用UPnP配置SDN端口转发

2020-07-21

我的上海电信500M宽带需要SDN光猫连接。这种光猫只能使用一款叫网络管家的APP设置。如果想通过外网访问内网的服务(比如NAS),需要配置虚拟服务器或者DMZ主机功能。网络管家APP都支持设置这些功能

电信网络管家功能
电信网络管家功能

如果你有公网IP(没有打客服电话),而且设置了DMZ主机(所有公网端口流量都转发给指定主机)或者虚拟服务器(指定公网端口流量转发到指定主机),你就可以通过公网IP加端口访问内网的服务。当然,80/443 这样的端口是不要想了,非知名端口都能正常使用。

So far so good。

如果你真的用起来,就会发现一个不大不小的问题。配置DMZ或者虚拟服务器需要指定内网主机IP,而内网主机的IP是光猫动态分配的。到目前为止,内网主机的IP会经常变化。而且网络管家APP没有开放DHCP配置功能。

怎么办呢?

最简单的办法是直接给内网主机设置固定IP。光猫是从小到大分配IP的,你可以从大到小设置,尽量不根自动分配的IP冲突。如果你不想折腾,读到这里就可以结束了。但这种方法有IP冲突的可能性。虽然很小(几乎不可能),但总觉得不优雅

有没有更好的办法呢?有,使用UPnP!

我们可以使用网络管家开启光猫的UPnP功能。

UPnP是干什么的呢?简单来说就是一种通信协议,局域网内主机的应用可以使用UPnP协议告诉光猫,说请你把公网某某端口的流量转发到我的IP的端口上。说白了就是动态配置光猫的端口转发规则。

UPnP协议比较复杂,没有必要深入了解所有细节,惟一要做的是找找有没有现成的工具。

我是目前主要写 go 语言,简单 google 了关键字upnp client golang,排在第一位的是英国一哥们开源的软件 goupnp

打开光猫的UPnP功能,运行 goupnp 的cmd/discoverall命令可以看到如下输出:

Location: http://*:5400/rootDesc.xml
USN: uuid:*::urn:schemas-upnp-org:service:WANPPPConnection:1
  Root v1.0 @ http://*:5400/rootDesc.xml
  Type: urn:schemas-upnp-org:device:InternetGatewayDevice:1
  Friendly name: XXX Dual Band Wireless Router XXX
  Num devices: 1
...

我就随手访问了这个 http://*:5400/rootDesc.xml链接,内容 xml,各字段含义我是不知道的,但有一些内容引起我的注意:

<device>
<deviceType>urn:schemas-upnp-org:device:WANConnectionDevice:1</deviceType>
<friendlyName>WANConnectionDevice</friendlyName>
<manufacturer>MiniUPnP</manufacturer>
<manufacturerURL>http://miniupnp.free.fr/</manufacturerURL>
<modelDescription>MiniUPnP daemon</modelDescription>
<modelName>MiniUPnPd</modelName>
<modelNumber>20150528</modelNumber>
<modelURL>http://miniupnp.free.fr/</modelURL>
<serialNumber>00000000</serialNumber>
<UDN>uuid:*</UDN>
<UPC>000000000000</UPC>

看起来这个光猫的UPnP功能是用MiniUPnP实现的。打开对应的网站http://miniupnp.free.fr/,果然是个UPnP的一个开源实现,同时提供服务器和客户端工具。因是MiniUPnP是用标准C开发的,所以很方便地移稙到路由器上。也难怪电信光猫使用它实现UPnP功能。

我用的是macos,不知道MiniUPnP能不能使用homebrew安装。Google 关键字miniupnp homebrew找到了对应的软件包miniupnp

执行brew install miniupnpc完成安装。

好了,准备工作结束,现在表演正式开始

如果你的公网IP是1.1.1.1,局域网IP是192.168.1.9,你本机的 nginx 监听在*:8080端口, 你想把公网的8888端口映射到本机的8080端口,你可以

upnpc -a 192.168.1.9 8080 8888 tcp

这里的upnpc就是MiniUPnP的客户端工具。-a表示添加

如果执行成功,你会在网络管家看到如下记录

网络管家UPnP记录
网络管家UPnP记录

这个时候你访问1.1.1.1:8888就能看到 nginx 的页面了。

如果想关闭端口映射,则可以执行

upnpc -d 8888 tcp

最后,你可以写一个脚本,在电脑开机连网后自动查询本机IP,然后通过upnpc将端口映射规则写入光猫;等电脑关机的时候再自动删除映射关系。一切都是那么的自然。

好了,感紧动手试试吧。

「taoshu」微信公众号