Programmatically Controlling a UPnP-Capable Firewall

 

By Knox North

This article covers how to control a Universal Plug and Play (UPnP) hardware Firewall by using VB script under Windows XP.  Many network configurations use a hardware firewall for both NAT (Network Address Translation) and for protection against port probing and other forms of attack.  NAT basically allows multiple computers to share the same IP address.  Microsoft has added new functions to Windows XP that can manage NAT.  This article covers my informal investigation into the NAT API's and explains how I tested them, and gives an example of a real-world use of these API's for enabling file transfer in IRC. 

Firewalls or routers that implement NAT solve a large problem of managing a limited number of IP addresses.  For example, the cable company can give you one IP address, but you can have multiple computers sharing that one IP address.  This works great for browsing the web, but creates problems when one computer wants to communicate with another computer using the computer's IP address.  Consider the following diagram:

Many protocols embed the fixed IP and ports of the computer inside packets: this doesn't work well behind a NAT Firewall. This means if the laptop sent its IP address inside a packet to another computer it would send 192.168.1.102 to the other computer. That computer would be unable to respond because from the Internet, you appear to only have the WAN (Wide Area Network) IP address that the cable company assigned to you. Even if you or the application figures out the WAN IP address and sends that, when the second computer responds, the firewall may not know which computer on the Local Area Network (LAN) to send the packet to.

One way to solve these kinds of problems is to manually configure the firewall to forward various ports to certain computers on the LAN. This works, but requires the end user to be adept at understanding pretty detailed information about IP addresses and ports. For example, if you're playing a multiplayer game that uses certain ports, you may need to go into your firewall and tell the firewall that you want all packets that come to port 6500 to go to the specific computer that you are playing the game on. This is port forwarding. Neverwinter Nights is an example of a multiplayer game that needs port forwarding in the firewall configuration to work.  An excellent source for how to accomplish port forwarding is Practically Networked's tutorial.

That brings us to Microsoft's attempts to simplify various networking problems from the end user's perspective. Microsoft has a broad strategy of having devices when they are brought into a LAN, they can be queried as to their functionality and services. Ultimately, they expect such items as thermostats and clocks to be network capable. Having devices and services cooperate with PC's is the goal of the UPnP organization, which is lead by Microsoft.  Universal Plug and Play is a set of protocols and API's that allow the devices to interoperate.

Obviously, a firewall is such a device on the network. Manufacturers are beginning to offer firewalls that offer UPnP capability. One of the solutions to the NAT problem described above is called NAT Traversal. This allows for applications to programmatically control functions within a UPnP capable Firewall.  Microsoft has included API's for UPnP and for NAT Traversal in Windows XP.  

My network (similar to the diagram above) consists of a Linksys BEFSR41 Firewall (Version 1.42.6, Mar 11 2002) that has a WAN port connected to a cable modem.  On the internal side (LAN), there are several computers, one of which is running Windows XP.   This is the computer that the code runs on.  Each computer is assigned an IP address by the Firewall using DHCP. If you try this yourself, you will need Windows XP and a UPnP-capable Firewall.

Microsoft offers examples of generic UPnP control in their development material using VB script, but doesn't cover the NAT specific API's other than by giving their C++ interfaces.  The Microsoft development material explained what DLL the API's were in.  The NAT API's (for example, IUPnPNAT) are covered in the Platform SDK.  I then ran the  OLE-COM Object Viewer and after some hunting around found an object:  Home Networking NAT Traversal via UPnP Configuration Manager.  This told me what I had not been able to find in the SDK documentation, mainly that the VersionIndependentProgID = HNetCfg.NATUPnP.  Along with the SDK documentation, this allowed for the development of the first VB script program.  (If you do this yourself, put this in a file that ends in a .vbs extension)

'The hard part is finding what VersionIndependentProgID to use

'This object is only used to get the collection of ports

Set theNatter = CreateObject( "HNetCfg.NATUPnP")

'put the collection of ports in this variable

Dim mappingPorts

Set mappingPorts = theNatter.StaticPortMappingCollection

MsgBox("Total number of ports is " & mappingPorts.Count)

'Show the user how the ports are being used

for each mappingPort in mappingPorts

MsgBox( mappingPort.Description & " " & mappingPort.ExternalPort & " " & mappingPort.Protocol & " " & mappingPort.InternalPort)

next

 

If you run this program, you will typically see it report 10 ports in use and then a series of results (from the MsgBox loop) of "FTP 21 TCP 21" followed by "Telnet 23 TCP 23" and so on. If you look in the list of Network Connections in Windows XP, you will find an "Internet Connection" of type "Internet Gateway". This is present if you have a UPnP-capable firewall. Bring up its properties and then settings, and you will see:

 

This is how Windows XP allows you to manually change the ports on the Linksys.  None are enabled in the picture above.  Linksys also gives you a way to edit these ports:

 

 

 

So you can see that we are programmatically reviewing the information that Windows XP shows you through a property screen, and that Linksys shows you through their configuration screens. Linksys "built in" the common port forwards: FTP, Telnet, and so on.

Now as a real life demonstration of how this functionality can be helpful, let's examine Internet Relay Chat (IRC).  IRC in general is a well-behaved protocol as far as firewalls go. IRC has a feature called Direct Client to Client (DCC) which allows computers to talk directly to each other without going through a server. However, when DCC is used behind a firewall, it suffers in that when one program initiates DCC for file transfer let's say, the initiating program sends its request through the normal channels telling the second computer to respond. It tells the second computer to respond to a certain IP and on a certain port. When the second computer responds to a firewall that hasn't been configured, that firewall will get an unexpected packet on an unexpected port and throw it away. This is the typical NAT problem that we've seen above. The DCC file transfer will fail. If we have a UPnP capable firewall, a smart IRC program could tell the firewall to expect packets on a certain port. So that's what this script does: 

'This program enables an IRC file transfer port

'And then puts up a prompt waiting for the user

'to be finished transferring files

Set theNatter = CreateObject( "HNetCfg.NATUPnP")

Dim mappingPorts

Set mappingPorts = theNatter.StaticPortMappingCollection

'We add a new port saying that externally accept from port 1024

'route to internal port 1024 on computer with IP 192.168.1.101

'Enabling the forward, and giving a name of the forward to be IRC

mappingPorts.Add 1024, "TCP", 1024, "192.168.1.101", TRUE, "IRC"

'

MsgBox("Total number of ports after add is " & mappingPorts.Count & ". Hit OK when you're done transfering")

'To uniquely specify a forward, you give the external port

'and the protocol - here we remove the forward that we added

mappingPorts.Remove 1024, "TCP"

MsgBox("We're done and the total number of ports is " & mappingPorts.Count)

 

This program will open the port and forward port 1024 from the firewall to the XP computer. Now, I hardcoded my IP address in the software above. This is ok for me, since my IP's rarely change. I leave it as an exercise for the reader to determine the IP of his computer programmatically or put it in manually like I did. The other thing I did was hardcode the port number to be 1024.  In the IRC program, (mIRC anyway) you can specify a range of ports to be used for DCC's.  In my case, I've specified the port range to be from 1024 to 1024. There's a couple of things you have to do to get DCC's to work this way behind a firewall. You set up IRC to use the server to determine the IP address so it finds your WAN IP not your local IP. Finally, you will need to enable Ident in mIRC and set up a port trigger in the firewall such that outgoing activity on the range of 6660-7000 enables incoming port 113.

So how do you use the program?  When you want to DCC a file transfer, run the program.  It will enable the port forward and wait.  When the file transfer (or DCC chat) is complete, click the button for the program to continue.  It will remove the port forward.  Just for fun, if you examine the Linksys UPnP Port-forward screen while the program is waiting, here is what you see:

Finally, why not just manually enable the port forward and leave it enabled all the time?   It is a vital security measure that the firewall is keeping unexpected packets out of my system for ALL ports.  I don't want to leave ANY of them open, unless I'm using them.  I'm sure in the future we will see IRC programs programmatically doing what we're doing here.  (Are you listening, Khaled Mardam-Bey?  He's the author of the famous mIRC program and deserves a lot of credit for writing a flexible IRC program)  While we're discussing security, it's worth pointing out that some think any UPnP is too much of a security risk.  See Steve Gibson's opinion on the matter.  I think what he says is true, but since we're already behind a NAT firewall, the risk is minimal.

There are limitations to Microsoft's and Linksys's implementation of NAT Traversal through the UPnP API's.  Although I haven't tested the limit, the total number of forwards simultaneously handled by the Linksys firewall is limited to perhaps 5 or so.  Another limitation by the Microsoft API's is that ranges are not covered.  Some games require many ports to be used and specify ranges of ports that need to be forwarded.  Finally, a security limitation exists with the current Microsoft implementation.  If a program sets up a port forward, the program itself is responsible for removing it.  The script above did that when you're finished with a file transfer.  However, if the program fails to remove the port forward, the forward stays in place.  Microsoft should have considered a port forward to be like any other system resource:  when a program ends normally or abnormally, the operating system should release all system resources being used by that program.     XP does this for memory, it should do this for port forwards.

You've seen how to use Windows XP and a UPnP firewall to script port forwarding.   This article gives you some help toward automating firewall configuration changes necessary for games and other programs.

 

The End

 

 

Thanks to:  Carolyn L. Kelley, Marriage Counseling in Boca Raton, Florida

Return to my home page

For good all round technical support, check out 5StarSupport

All trademarks and service marks are the property of their respective owners.

© 2002, 2003 Knox North  All Rights Reserved.