是否可以使用UPNP协议在路由器上使用ESP8266进行自动端口转发?
即使我不在家,我也需要能够访问我的ESP8266模块。 目前,我已在路由器设置中手动配置端口转发。
但是在未来,为了使我的项目成为商业产品,它需要能够进行自动端口转发,因为这对普通用户来说是一个障碍。
在互联网上,我在ESP8266上发现了一些关于UPNP的事情,但它不是关于端口转发。
非常感谢你!
答案 0 :(得分:6)
你可以看一下我为此制作的图书馆: https://github.com/ofekp/TinyUPnP
我在包装内有一个IOT设备(LED灯)的例子,由于声誉低,我无法附加链接。
您可以查看示例代码。全部用于ESP8266。
使用非常简单,只需使用要打开的端口调用addPortMapping,就像示例中所示。
您必须每36000 (LEASE_DURATION)
秒执行此操作,因为UPnP是基于租约的协议。
宣告:
unsigned long lastUpdateTime = 0;
TinyUPnP *tinyUPnP = new TinyUPnP(-1); // -1 means blocking, preferably, use a timeout value (ms)
设定:
if (tinyUPnP->addPortMapping(WiFi.localIP(), LISTEN_PORT, RULE_PROTOCOL_TCP, LEASE_DURATION, FRIENDLY_NAME)) {
lastUpdateTime = millis();
}
循环:
// update UPnP port mapping rule if needed
if ((millis() - lastUpdateTime) > (long) (0.8D * (double) (LEASE_DURATION * 1000.0))) {
Serial.print("UPnP rule is about to be revoked, renewing lease");
if (tinyUPnP->addPortMapping(WiFi.localIP(), LISTEN_PORT, RULE_PROTOCOL_TCP, LEASE_DURATION, FRIENDLY_NAME)) {
lastUpdateTime = millis();
}
}
我只用我的D-Link路由器检查过它。
对任何对图书馆运作方式感兴趣的人:
Location
的HTTP标头的消息进行响应。Location
是包含IGD(Internet网关设备)API的XML文件的链接,以便创建所需的调用,将新的端口映射添加到您的网关路由器。<serviceType>urn:schemas-upnp-org:service:WANPPPConnection:1</serviceType>
,这正是图书馆正在寻找的。 li>
eventSubURL
标记,该标记是路由器IGD API的链接。 (基本URL也显示在标记URLBase
)SCPDURL
标记,该标记是指向另一个XML的链接,该XML描述了可用于服务及其参数的命令。该软件包跳过这个阶段,因为我认为许多路由器的查询类似,但情况可能并非如此,因此需要检查。接头:
"POST " + <link to service command from XML> + " HTTP/1.1"
"Content-Type: text/xml; charset=\"utf-8\""
"SOAPAction: \"urn:schemas-upnp-org:service:WANPPPConnection:1#AddPortMapping\""
"Content-Length: " + body.length()
体:
"<?xml version=\"1.0\"?>\r\n"
"<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\" s:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">\r\n"
"<s:Body>\r\n"
"<u:AddPortMapping xmlns:u=\"urn:schemas-upnp-org:service:WANPPPConnection:1\">\r\n"
" <NewRemoteHost></NewRemoteHost>\r\n"
" <NewExternalPort>" + String(rulePort) + "</NewExternalPort>\r\n"
" <NewProtocol>" + ruleProtocol + "</NewProtocol>\r\n"
" <NewInternalPort>" + String(rulePort) + "</NewInternalPort>\r\n"
" <NewInternalClient>" + ipAddressToString(ruleIP) + "</NewInternalClient>\r\n"
" <NewEnabled>1</NewEnabled>\r\n"
" <NewPortMappingDescription>" + ruleFriendlyName + "</NewPortMappingDescription>\r\n"
" <NewLeaseDuration>" + String(ruleLeaseDuration) + "</NewLeaseDuration>\r\n"
"</u:AddPortMapping>\r\n"
"</s:Body>\r\n"
"</s:Envelope>\r\n";
我希望这会有所帮助。
答案 1 :(得分:2)
我不明白为什么不。 UPnP实现多个配置文件,您感兴趣的配置文件名为IGD (Internet Gateway Device),大多数家庭路由器实现这些配置文件以允许本地网络上的客户端应用程序(例如Skype,uTorrent等)映射路由器NAT上的端口。 / p>
UPnP在IP multicast上工作,以发现和宣布通过地址239.255.255.250
实施UPnP服务的设备。对此类通知感兴趣的设备订阅此多播组并侦听端口1900
。实际上,UPnP本身并不提供发现机制,而是依赖于名为SSDP (Simple Service Discovery Protocol)的协议来发现本地网络上的主机。
所需要的只是一个绑定到上述地址和端口的UDP套接字,用于在您的家庭组播组上订阅和发布消息。您需要使用SSDP的实现来发现您的路由器,一旦您发现了路由器,您就可以使用围绕SOAP enveloppes的UPnP发送命令。
Posix C中有许多UPnP IGD配置文件的实现,您可以重复使用它们并移植到ESP 8266(例如MiniUPnP,gupnp-igd)。