2017-06-09 315 views
1

是否可以在使用ESP8266的路由器上使用UPNP协议进行自动端口转发?ESP8266 UPnP端口转发 - 物联网

即使我离家出走,我也需要访问我的ESP8266模块。 目前我已在我的路由器设置中手动配置端口转发。

但是在未来,为了让我的项目成为一个商业产品,它需要能够自动进行端口转发,因为这对于普通用户来说是一个障碍。

在互联网上,我发现了一些在ESP8266上谈论UPNP的东西,但它不是关于端口转发。

非常感谢您提前!

回答

2

我不明白为什么不。 UPnP实现了多个配置文件,您感兴趣的配置文件名为IGD (Internet Gateway Device),大多数家庭路由器都实现了允许本地网络(例如Skype,uTorrent等)上的客户端应用程序映射路由器NAT上的端口。

UPnP通过IP multicast工作,发现并宣布在地址239.255.255.250上实施UPnP服务的设备。对此类通告感兴趣的设备订阅这个多播组并在端口1900上侦听。实际上,UPnP本身并不提供发现机制,但依靠名为SSDP (Simple Service Discovery Protocol)的协议来发现本地网络上的主机。

所需要的只是绑定到上述地址和端口的UDP套接字,以便在您的家庭多播组上订阅和发布消息。您需要使用SSDP的实现来发现您的路由器,一旦发现了您的路由器,就可以使用包裹在SOAP信封上的UPnP发送命令。

Posix C中有很多UPnP IGD配置文件的实现,您可以重复使用并连接到ESP 8266(例如MiniUPnP,gupnp-igd)。

5

你可以看看我的图书馆,我只是做了该: https://github.com/ofekp/TinyUPnP

我对包内的IOT装置(LED灯)的一个例子,我不能将链接附加由于低信誉。

你可以看看示例代码。全部为ESP8266制造。 使用起来非常简单,只需调用addPortMapping和要打开的端口即可,正如示例中所示。 因为UPnP是基于租约的协议,所以您必须每36000 (LEASE_DURATION)秒完成一次。

声明:本

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路由器检查它。

感兴趣的人在库中是如何工作的:

  1. 它发送M_SEARCH消息UPnP的UDP多播地址。
  2. 网关路由器将回应一条消息,其中包含一个名为Location的HTTP标头。
  3. Location是一个指向包含IGD(互联网网关设备)API的XML文件的链接,以便创建所需的呼叫,从而将新的端口映射添加到网关路由器。
  4. 在XML中描述的其中一项服务是<serviceType>urn:schemas-upnp-org:service:WANPPPConnection:1</serviceType>,这是图书馆正在查找的内容。
  5. 该服务将包含一个eventSubURL标记,它是链接到您的路由器的IGD API的标记。 (基本URL也显示在标记URLBase下的同一文件中)
  6. 使用基本URL和WANPPPConnection链接,您可以向将添加UPnP规则的路由器发出HTTP查询。
  7. 作为一个附注,XML中描述的服务还包含一个SCPDURL标记,该标记是另一个XML的链接,描述了可用于服务及其参数的命令。这个包跳过了这个阶段,因为我认为这个查询对于很多路由器来说是相似的,但这可能不是这种情况,所以这是由你来检查的。
  8. 从这个阶段开始,软件包将使用HTTP查询向路由器发出服务命令。实际的查询可以看到代码很清楚,但有兴趣的人士:

页眉:

"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"; 

我希望这有助于。