Is it possible to use the UPNP protocol for automatic port forwarding on the router using ESP8266?
I need to be able to access my ESP8266 module even when I am away from home. Currently I have configured port forwarding manually in my router settings.
But in the future, in order for my project to become a commercial product, it needs to be able to do automatic port forwarding as this would be a barrier for the average user.
On the internet I found something talking about UPNP on ESP8266, but it was not about port forwarding.
Thank you very much in advance!
You can have a look at my library that I made just for that: https://github.com/ofekp/TinyUPnP
I have an example for an IOT device (LED lights) within the package, I cannot attach the link due to low reputation.
You can have a look at the example code. All made for ESP8266.
Very simple to use, just call addPortMapping with the port you want to open, just as showed in the example.
You have to do this every 36000 (LEASE_DURATION)
seconds, since UPnP is lease based protocol.
Declare:
unsigned long lastUpdateTime = 0;
TinyUPnP *tinyUPnP = new TinyUPnP(-1); // -1 means blocking, preferably, use a timeout value (ms)
Setup:
if (tinyUPnP->addPortMapping(WiFi.localIP(), LISTEN_PORT, RULE_PROTOCOL_TCP, LEASE_DURATION, FRIENDLY_NAME)) {
lastUpdateTime = millis();
}
Loop:
// 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();
}
}
I only checked it with my D-Link router.
To anyone interested in how the library works:
Location
.Location
is a link to an XML file containing the IGD (Internet Gateway Device) API in order to create the needed calls which will add the new port mapping to your gateway router.<serviceType>urn:schemas-upnp-org:service:WANPPPConnection:1</serviceType>
which is what the library is looking for.eventSubURL
tag which is a link to your router's IGD API. (The base URL is also depicted in the same file under the tag URLBase
)SCPDURL
tag which is a link to another XML that depicts commands available for the service and their parameters. The package skips this stage as I assumed the query will be similar for many routers, this may very well not be the case, though, so it is up to you to check.Headers:
"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()
Body:
"<?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";
I hope this helps.
I don't see why not. UPnP implements multiple profiles, the one you are interested in is named IGD (Internet Gateway Device), which most home routers implement to allow client applications on the local network (e.g Skype, uTorrent, etc.) to map ports on the router's NAT.
UPnP works over IP multicast to discover and announce devices implementing UPnP services over the address 239.255.255.250
. Devices interested in such announcements subscribe to this multicast group and listen on port 1900
. In fact, UPnP does not itself provide a discovery mechanism, but relies on a protocol called SSDP (Simple Service Discovery Protocol) to discover hosts on the local network.
All that's needed is an UDP socket bound to the aforementioned address and port to subscribe and publish messages on your home multicast group. You'd need to use an implementation of SSDP to discover your router, once you have discovered your router, you can send commands using UPnP wrapped around SOAP enveloppes.
There are many implementations of the UPnP IGD profile in Posix C, which you may reuse and port to the ESP 8266 (e.g MiniUPnP, gupnp-igd).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With