ESP8266 UPnP端口转发 - 物联网

Jul*_*oso 3 upnp iot esp8266

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

即使我不在家,我也需要能够访问我的ESP8266模块.目前我已在路由器设置中手动配置端口转发.

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

在互联网上,我在ESP8266上发现了一些关于UPNP的事情,但它不是关于端口转发的.

非常感谢你提前!

ofe*_*ekp 7

您可以查看我为此制作的库:https: //github.com/ofekp/TinyUPnP

我有一个包装内的IOT设备(LED灯)的例子,由于声誉低,我无法附加链接.

您可以查看示例代码.全部用于ESP8266.使用非常简单,只需使用要打开的端口调用addPortMapping,就像示例中所示.(LEASE_DURATION)由于UPnP是基于租约的协议,因此每36000 秒必须执行此操作.

宣布:

unsigned long lastUpdateTime = 0;
TinyUPnP *tinyUPnP = new TinyUPnP(-1);  // -1 means blocking, preferably, use a timeout value (ms)
Run Code Online (Sandbox Code Playgroud)

建立:

if (tinyUPnP->addPortMapping(WiFi.localIP(), LISTEN_PORT, RULE_PROTOCOL_TCP, LEASE_DURATION, FRIENDLY_NAME)) {
    lastUpdateTime = millis();
}
Run Code Online (Sandbox Code Playgroud)

环:

// 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();
    }
}
Run Code Online (Sandbox Code Playgroud)

我只用我的D-Link路由器检查过它.

对任何对图书馆如何运作感兴趣的人:

  1. 它向UPnP UDP多播地址发送M_SEARCH消息.
  2. 网关路由器将使用包含HTTP头的消息进行响应Location.
  3. Location 是指向包含IGD(Internet网关设备)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查询向路由器发出service命令.可以在代码中清楚地看到实际查询,但对于任何感兴趣的人:

头:

"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()
Run Code Online (Sandbox Code Playgroud)

身体:

"<?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";
Run Code Online (Sandbox Code Playgroud)

我希望这有帮助.