Python:在路由器后打开监听端口(upnp?)
我开发了一个应用程序,基本上就是一个小型的FTP服务器,可以在启动时指定要共享的目录。我使用了ftplib来搭建这个服务器,因为它非常简单。现在唯一的问题是,如果你在路由器后面,就需要手动在路由器上转发端口,而我发现这对我的用户(也就是我的同事和客户)来说有点复杂。
所以我一直在寻找一个简单的解决方案来打开端口,但我发现大多数API都太复杂了,我根本搞不懂。有没有人知道一个相对简单的解决方案可以实现呢?
注意:这个应用主要是在Windows上使用,虽然如果能跨平台兼容那就更好了。如果有一个仅适用于Windows的更简单的解决方案,我会更倾向于选择那个。
谢谢!
5 个回答
看起来有几个选择,其中一个是 miniupnp。还有 GNUPnP 的 Python 绑定,可以在这里找到。如果你使用 Windows,miniupnp 可以正常工作,或者你也可以选择纯 Python 的 miranda-upnp。
这里有一个很好的例子,展示了如何使用 Python 的 GNUPnP 绑定来在路由器上打开端口,可以在这里查看。在这个例子中,租约时间被设置为 0,这意味着没有时间限制。关于 add_port 的定义,可以查看 这里。
一个简单的例子可能是:
#! /usr/bin/python
import gupnp.igd
import glib
from sys import stderr
my_ip = YOUR_IP
igd = gupnp.igd.Simple()
igd.external_ip = None
main = glib.MainLoop()
def mep(igd, proto, eip, erip, port, localip, lport, msg):
if port == 80:
igd.external_ip = eip
main.quit()
def emp(igd, err, proto, ep, lip, lp, msg):
print >> stderr, "ERR"
print >> stderr, err, proto, ep, lip, lp, msg
main.quit()
igd.connect("mapped-external-port", mep)
igd.connect("error-mapping-port", emp)
#igd.add_port("PROTO", EXTERNAL_PORT, INTERNAL_IP, INTERNAL_PORT, LEASE_DURATION_IN_SECONDS, "NAME")
igd.add_port("TCP", 80, my_ip, 8080, 86400, "web")
main.run()
你想要的协议叫做IGD(互联网网关设备),它是基于UPNP的。这个协议可以让你的程序找到网络上的路由器(通过UPNP),然后请求路由器转发一个特定的端口。
大多数家用路由器都支持这个功能,很多服务,比如BitTorrent或者多人游戏,也会用到这个技术。不过,使用或实现起来有点复杂。有几个开源库支持IGD,其中一个最简单的(而且可以在不同平台上使用)是miniupnp:你可以查看 http://miniupnp.free.fr/
这是一个关于miniupnp的简单示例。它在找到的网关上创建了一个映射,把外部端口43210连接到与发现的网关相连的接口上的43210端口。
import miniupnpc
upnp = miniupnpc.UPnP()
upnp.discoverdelay = 10
upnp.discover()
upnp.selectigd()
port = 43210
# addportmapping(external-port, protocol, internal-host, internal-port, description, remote-host)
upnp.addportmapping(port, 'TCP', upnp.lanaddr, port, 'testing', '')