Python: 在路由器后面打开一个监听端口(upnp?)

23
我开发了一个应用程序,实际上只是一个具有在启动时指定要共享的目录功能的小型FTP服务器。我正在使用ftplib作为服务器,因为它很容易上手。唯一的问题是,如果您在路由器后面,您必须手动在路由器上转发端口,并且我发现这对我的用户(也就是同事/客户)来说有点太复杂了。
因此,我一直在寻找一个简单的解决方案来打开端口,但我发现大多数API都太复杂了,超出了我的理解范围。请问是否有人知道一个相对简单的实现方案?
注意:它将主要在Windows上使用,虽然跨平台兼容性将受到欢迎。如果有一个仅适用于Windows的更简单的解决方案,我会选择它。
谢谢!

@Falmarri:你可以使用UPnP来实现这一点,它是一个标准,可以动态地打开防火墙中的开放端口;因此,这不是路由器/制造商特定的。 - ZeissS
5个回答

15

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', '')

谢谢,@lionello,发现得好!我稍微编辑了你的修改。 - datashaman

13
您所需要的协议称为IGD(即Internet Gateway Device),基于UPNP。它允许客户端程序(您的程序)通过使用UPNP,在网络上发现路由器,然后请求其转发特定端口。
大多数家庭路由器都支持此功能,而且很多服务(如BitTorrent或多人游戏)也使用这种技术,但是使用或实现起来有些复杂。有几个开源库支持IGD,其中一个最简单的跨平台库是“miniupnp”。请参见http://miniupnp.free.fr/

4

看起来有几个选项,其中一个是miniupnp。还有GNUPnP的python绑定在这里。对于Windows,minupnp将起作用,或者您可以使用miranda-upnp进行纯Python。

有一个很好的例子,展示了如何使用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()

2

这里有一篇文章,讲解如何使用win32com和Windows IGD COM对象。


0

我寻找了很多天,但无法使用pip为Python 3安装miniupnpc。

我通过在这里找到的实现解决了这个问题,该实现适用于Python 2。

我对其进行了分支并进行了更改,以便在Python 3上使用,您可以在这里找到它。

这个实现是我见过的最简单的,而且运行良好。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接