ESP8266 UPnP端口转发 - 物联网

时间:2017-06-09 15:24:09

标签: iot esp8266 upnp

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

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

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

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

非常感谢你!

2 个答案:

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

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

  1. 它向UPnP UDP多播地址发送M_SEARCH消息。
  2. 网关路由器将使用包含名为Location的HTTP标头的消息进行响应。
  3. Location是包含IGD(Internet网关设备)API的XML文件的链接,以便创建所需的调用,将新的端口映射添加到您的网关路由器。
  4. XML中描述的服务之一是<serviceType>urn:schemas-upnp-org:service:WANPPPConnection:1</serviceType>,这正是图书馆正在寻找的。
  5. 该服务将包含eventSubURL标记,该标记是路由器IGD API的链接。 (基本URL也显示在标记URLBase
  6. 下的同一文件中
  7. 使用基本URL和WANPPPConnection链接,您可以向将添加UPnP规则的路由器发出HTTP查询。
  8. 作为旁注,XML中描述的服务还包括SCPDURL标记,该标记是指向另一个XML的链接,该XML描述了可用于服务及其参数的命令。该软件包跳过这个阶段,因为我认为许多路由器的查询类似,但情况可能并非如此,因此需要检查。
  9. 在此阶段,程序包将使用HTTP查询向路由器发出service命令。实际查询可以在代码中清楚地看到,但对于任何感兴趣的人:
  10. 接头:

    "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(例如MiniUPnPgupnp-igd)。