Pawan Kumar
Pawan Kumar

Reputation: 231

How to achieve double NAT port forwarding via upnp programmatically

I am trying to achieve double NAT working with UPNP. My PC connection is as follows:
Internet -> Router 1 -> Router 2-> PC
I have successfully done port forwarding on the Router 2, but not able to do on router 1. Due to which packets from the server(which is on Internet) are not able to reach PC.
Gone through few document how to tackle but mostly found manual way like bridge the network or put the lan wire.
I am rather looking for the some recursive solution using UPNP protocol to do the port forward on both routers. I guess torrent, skype does the same.
How to get the network interface related to router 1 and then port forward on that Network ?

Any help would be highly appreciated.

Thanks,
Pawan

Upvotes: 7

Views: 8556

Answers (2)

Chris
Chris

Reputation: 3354

With the upnpc cli tool I've been able to get Double NAT port forwarding working.

For my example, let's say I want port 6667 to be forwarded to my machine, 192.168.50.123, behind a double NAT. The first layer of NAT has the IP range 192.168.1.1-255, and then 2nd layer has IP range 192.168.50.1-255.

On a machine inside the 2nd layer of NAT, just setup port forwarding with upnpc like normal.

$ upnpc -a 192.168.50.123 6667 6667 tcp
...
$ upnpc -l   # this will confirm the rule is in place
...

Now for the slightly tricky part. I now issue UPNP requests to the outer layer NAT. Since the usual SSDP discovery won't work, I have to specify the XML root description URL manually. It's often something standard like http://192.168.1.1:5000/rootDesc.xml, though on some hardware the port number is randomized. I find just port scanning the gateway address will eventually reveal it.

Now that I have the rootDesc url, http://192.168.1.1:5000/rootDesc.xml, I then issue UPNP command to the outer layer NAT:

$ upnpc -u "http://192.168.1.1:5000/rootDesc.xml" -a 192.168.1.XX 6667 6667 tcp
...
$ upnpc -u "http://192.168.1.1:5000/rootDesc.xml" -l   # this will confirm the rule is in place
...

With the -u option instead of discoverying the rootDesc, it just uses the URL provided. The address 192.168.1.XX should be the 2nd layer network's IP address on as seen by the 1st network. When running the first set of UPNP commands this will be shown since it's the "external" address from that NAT's perspective.

With that now setup, traffic will go like this:

<INTERNET> -->  MY_PUBLIC_IP -> 192.168.1.XX -> 192.168.50.123

Upvotes: 0

Roman Khimov
Roman Khimov

Reputation: 5022

There is an IGD-PCP IWF specification that tries to solve similar problem, although it assumes PCP support on your "Router 1", not UPnP. So let's try to approach this issue from a pure theoretical point of view with two plain UPnP routers/NAT devices.

There are several distinct steps of UPnP communication as per UPnP Device Architecture version 2.0:

  • addressing
  • discovery
  • description
  • control
  • eventing
  • presentation

Addressing is of little interest for us, let's assume proper DHCP everywhere and be done with it. Eventing and presentation are also almost useless in our case. So the main things to be concerned about are discovery, description and control.

Discovery works via SSDP message exchange. SSDP uses UDP for its transport with port number 1900 (by default) and well-known multicast address.

Description starts with URL provided by the device at discovery phase, the control point (that is PC in our case) needs to issue an HTTP GET request on this URL and that means it uses TCP as a transport protocol with devices IP address (unicast).

Control starts with URL provided by the device in its description, and it uses SOAP on top of HTTP on top of TCP which in turn also means unicast IP for us.

So, what all of that means for double NAT is that in description and control steps of UPnP interaction we have zero problems communicating from PC to Router 1 as all of that is just standard TCP with unicast IP addresses. But to get to the description step we need to have a URL of Router 1, so let's take a closer look at how this URL is acquired the normal way.

There are two main mechanisms for discovery — advertising (when the device periodically multicasts some information about it) and search (when the control point sends multicast search message and the device answers to that with unicast response). Obviously, by default our PC behind the Router 2 can't get multicast advertisements from Router 1 and the Router 1 can't get multicast search messages from PC, so we have a problem here and the question now is whether there is a possibility for communication without multicast.

Luckily, the same architecture document says:

In addition, a control point is allowed to unicast a discovery message to a specific IP address on port 1900 or on the port specified by the optional SEARCHPORT.UPNP.ORG header field (which supersedes port 1900 for this use), searching for a UPnP device or service at that specific IP address.

...

All devices shall listen to incoming unicast search messages on port 1900 or, if provided, the port number specified in the SEARCHPORT.UPNP.ORG header field and shall respond if any of their root devices, embedded devices or services matches the search criteria in the discovery message.

And this means that if you know the Router 1 IP address (from Router 2 side, of course), you can (and most importantly, allowed by specification to) communicate with it with unicast UDP messages and that is also NAT-friendly, so not an issue to be done from PC behind the Router 2.

The only thing left is getting Router 1 IP address. Unfortunately, there is no easy standard way to do that, but you have at least two options: tracerouting (in whatever fashion you want) and brute force IP scanning (most probably, the potential set of IPs for Router 1 is limited).

Now you can communicate with the Router 1, but there is still one minor thing you should always remember while communicating with it — in any internal UPnP messages you should use Router 2 IP address (as seen from Router 1 side) and its ports. Like in NewInternalClient parameter of AddPortMapping action on Router 1 you should use Router 2 IP. This, BTW, raises a question of Router 2 IP, but you can get that via Router 2 UPnP ExternalIPAddress variable of WANIPConnection service (this service is required for IGDs to implement).

So, to summarize:

  • this technically can be done, although I doubt that any standard library would do that for you
  • two things you need are:
    • Router 2 "external" IP and you get that via ExternalIPAddress variable of WANIPConnection UPnP service
    • Router 1 "internal" IP (from Router 2 side), that requires tracerouting or scanning
  • given Router 1 IP you just need to use unicast messaging at discovery step instead of multicast
  • everything else should just work, with only caveat of using Router 2 "external" IP instead of PCs IP in the UPnP messages

Upvotes: 2

Related Questions