UPNP port forwarding – The easy way
From my experience I noticed that the NATUPnP library is pretty unstable when it comes down to UPNP (mostly refusing to work on some routers regarding if the router is UPNP enabled or not) I decided to make a simple walk-through to help people resolve these kind of issues and aid them in creating a program that manual port forwarding is not needed, at least for UPNP enabled routers.
So, let’s get started. First you need to download the Mono.Nat library which can be found here. When the download is complete extract the contents of the .zip file anywhere you like.
In order to be able to take advantage of the library we need to locate the file we have extracted and add it as a reference to our project then import it in your project using
Now it’s time for some coding.
We will need to add a few lines in our class constructor.
The following event will trigger the DeviceFound method (which we will be adding shortly) when a new device (router) is detected.
NatUtility.DeviceFound += DeviceFound;
The following event will trigger the DeciceLost method (which again we will be adding shortly) when the device goes offline.
NatUtility.DeviceLost += DeviceLost;
And finally .StartDiscovery will initiate the search for active devices.
Now it’s time to add the methods to the above events.
private void DeviceFound(object sender, DeviceEventArgs args)
INatDevice device = args.Device;
// on device found code
private void DeviceLost(object sender, DeviceEventArgs args)
INatDevice device = args.Device;
// on device disconnect code
Now that we have our two main event methods we can control and manipulate the ports in the devices by adding specific lines in our DeviceFound method, for example:
Adding the following line will allow TCP connections on port 80:
device.CreatePortMap(new Mapping(Protocol.Tcp, 80, 80));
The following line will remove/close the port we added above:
device.DeletePortMap(new Mapping(Protocol.Tcp, 80, 80));
To display all the port maps that are currently added in the device:
foreach (Mapping portMap in device.GetAllMappings())
To display the external IP:
In addition, if you want to check if a specific map already exists in the device you can check it by using the following method (the method bellow checks TCP port 80):
If the public port (or private port, both should work equally good) is -1 then no map on that port exists on the device.
This should be enough to get you going. Happy coding !
The function was called successfully.
How do I get External IP back after some time?
Calling this function does not work.
Might give an example.
I need to send a message to a computer.
I have the external ip internal ip and port where that computer listening .
as I can make a method to return my external ip using your library.
I don’t have a router I have created a hosted network using my wifi card in my laptop. I want to forward all the user connected to my hosted network while making a http request (port 80) to be forwarded to http://localhost:8080
What is the license?
Based on https://github.com/mono/Mono.Nat this library is under the The MIT License.
Hi, never mind about that last comment, it appears that, despite having uPnP enabled my router at just doesn’t like uPnP, it works fine on my laptop at home.
Thanks, for this quick how-to guide. :)
Glad to know you found a solution to your problem :)
When using device.GetAllMappings() I get MappingException: “Error 402: Invalid Argument”
I’ve done it the same way as you have done it also.
Hi, really interested in this DLL but I’m working in a Wince 5.0 platform (.Net 3.5). Do you have a dll that’s built for same ???? Thanks in Advance.
Mono.Nat is an open source library. You can find the source code at https://github.com/mono/Mono.Nat
You can compile the library with the .NET framework that suits your needs and/or do any modifications you might want to do as well.
how do you change the name it leaves on the router port forawarding it says mono.nat i want it to say something else
The Mapping object has a Description property. You can change that one to the name you would like.
can u give me an example like this
device.CreatePortMap(new Mapping(Protocol.Tcp, 27016, 27016, Description));
Hi, does not work for me, the console does not display any messages when started and I tried to put to record a log, but the log records empty.
My router has UPnP.
Here is the code:
Is the DeviceFound found event being raised ?
In some cases it might be quite problematic to use standard UPNP libraries if the device it self does not implement the UPnP protocol according to the standards. One of the banes that using UPNP as a solution for port forwarding sadly.
If this is the case you don’t really have a lot of options left, even if you bother messing around with the library’s code to get it working it will probably have the same issue on another device.
If the aim is to port forward your own server’s port take a look at the UDP hole punching techniques, if not, then I am afraid is down to the user to do the port forwarding manually.
But the strange thing is the fact that the log is not recorded anything. I believe he was to record at least the connection information.
I read elsewhere that the log serves precisely for this, when there is no upnp, is to write to the log that the connection failed.
Unfortunately I did not find any examples anywhere ready to test.
It may be something wrong in my project.
I need this because I am building a project of remote access to the company I work for, and it is not feasible to configure port for all customers.
Using your code a log file is generated when the class is instantiated. Even when the discovering fails there are around 10 lines of log entries in the file (based on my tests results). Do you have administration rights to write to the location you are trying to write the log ?
If it’s for a company I’d go for the UDP hole punching technique I mentioned above (similar to how TeamViewer/LogMeIn/Skype etc operates), since it is more reliable and won’t fail if the router does not support UPNP or if it doesn’t obey the UPNP standards.
If I will have a definite answer I will post it here
Great, I would be interested to know as well :)
Just to be clear… if my router is UPNP disable, Does the port forwarding still work?
Would my app forward to the port I specify at device.CreatePortMap(new Mapping(Protocol.Tcp, XXX, XXX)); ???
The answer is no, if the router doesn’t support UPNP or if it’s disabled then the above method will not work.
If you have access to the server you can use the hole punching technique to establish connection between the server and the client (this doesn’t rely on UPNP) without the client need to port forward any ports. Take a look at http://www.fluxbytes.com/csharp/udp-hole-punching-implementation-in-c/
But if both cases are not possible, meaning, the client’s UPNP is disabled and you have no access to the server in order to implement the hole punching, then you are left with no other alternative than to tell the client to manually port forward specific ports.
Thanks for the informative answer… I have another question if you don’t mind.
Does the implementation support both IPv4 and IPv6 (or dual) ?
Sadly I can’t give you a precise answer as I didn’t have the chance to test IPv6 and UPNP myself yet, so the correct person to answer that would probably be the author of the library (http://monotorrent.blogspot.co.uk/2011/03/mononat-110.html).
Theoretically it shouldn’t be an issue since as you can see in the example above you don’t specify the address yourself, just the incoming and outgoing ports. My assumption would be that if the router actually supports the technology (UPNP port forwarding with IPv6 addresses) then it should be forwarded properly internally. But as I said, this is merely my assumption till I get to test it out myself.
From what I’m aware the library should work equally good in VB.NET as well.
You will only need to convert the above example to VB, I would recommend trying http://www.developerfusion.com/tools/convert/csharp-to-vb/ and just correct any mistakes it produces during the conversion.
Is there something like this for Visual Basic.Net?