Quantcast
Viewing all articles
Browse latest Browse all 1449

VB6 - NAT Traversal

A NAT router is an excellent way to protect your computer network from outside hackers. The normal way to allow an outside host to connect with an internal host sitting behind a NAT router is to manually add a port forwarding address to the router setup. Setting up a router is not a simple task for the average user, and some routers have restricted access (especially public WiFi routers). To understand how to allow a host to connect with your program through a NAT router without adjusting the router setup, you must first understand how a NAT router works. Since we are interested in TCP connections, we will restrict our discussion to this type of connection.

All outbound connection requests (SYN request) are allowed through the router. At this point, the connection and it's translation are added to a NAT table. Your computer initiated the request using it's private IP address (eg. 192.168.1.5) and it's first available port (eg. 50342). The NAT router does the same thing. It uses the public address (eg. 201.34.87.52) and it's first available port (eg. 54671) and translates the outbound request to use these values. The other end only sees the router values. It never sees the values that your computer used. The values added to the NAT table on a SYN request include all 4 values:
Private IP Private Port Public IP Public Port
192.168.1.5 50342 201.34.87.52 54671
Most routers will allow about 60 seconds for this initial connection request to be acknowledged. Otherwise, it times out and is removed from the table. The connection acknowledgement (SYN-ACK) from the other end is received by the router, translated back to the private values, and forwarded to your computer. Once the connection is established, the inactivity timeout is much longer (say 24 hours), but will vary with the router.

So to traverse a NAT router without changing it's settings, we must create the NAT table entry and then connect to it before it times out. To accomplish this, we use a third party server which supplies the connecting IP address and port. Seems simple enough, but there is a complication. TCP standards do not allow us to share a port. So we will just close the existing connection and open it again with the same port number. There are 2 problems with this approach. One is that there is a TIME_WAIT after a connection is closed, which is to allow for straggling packets to be received.The other issue is that the newer versions of Microsoft sockets don't allow us to pick and choose the internal port number on a TCP connection request. It automatically chooses the first available port. So I set out to find a resolution to these issues.

To enable each side to connect to each other, we must kill the connection to the server without leaving the socket in a TIME_WAIT state. To do this, we set the "SO_LINGER" & "SO_REUSEADDR" options when we connect to the server. When we receive instructions from the server with the IP address & port number of the other end, we kill the existing socket and initiate a connection request using the same local IP address and port to the remote IP address and port. That creates a temporary NAT Table entry in the router.

When both sides are connected to the server, the server sends to each side the IP and port from the other side. Both ends will kill the existing socket that connects it to the server, create a new socket on the same local IP & port, and send a connection request to the other end. Don't ask me how this works, but the first one to receive the SYN request sends a SYN-ACK to the other end. This is enough to establish a connection and extend the timeout on the NAT router. Both ends will just have a connected socket (no listening socket).

So why are we going to this length to establish a connection? We want to allow a direct connection between 2 parties without the necessity of having the server forward all the information from both ends (as in a proxy server). The only purpose of the server is to supply the necessary information to establish that connection. Once directly connected, the entire session can be encrypted, and the server has no record of it.

The attached programs (NAT.vbp & Server.vbp) allow us to test this functionality. The server is set up to listen on port 24 using "SimpleServer.cls". Being a server, firewalls and routers must be setup to allow outside connections on port 24. To test "NAT.vbp", I added a NAT router between one of my computers and the local network, and a different NAT router to a second computer. This created a double NAT situation between these 2 particular computers, but a single NAT between each computer and the rest of the local network. The server program (Server.vbp) I set up on the local network. That left all 3 computers on separate networks. As each Nat.vbp connects to the server program, the server will display the connecting IP address and port. Machines operating from behind a NAT router will display the IP address and port of the NAT router public interface, instead of the computer's local IP address and port. Then the Trigger button on the server was clicked to send instructions to the 2 test computers. It took about 1 second for the connection to be established between the 2 test computers.

I had a great deal of difficulty getting this to work because of the vintage of one of the routers. Most routers will assign the same public port to a connection when it is using the same Private IP address and port. The older router however incremented the Public port number with each connection. I got around this problem by adding 1 to "sAddr" in the "SndConnect" routine of the machine behind the newer router.
Code:

mSocket.TCPConnect(sAddr, lPort + 1, PortListen)
You can test how your own router behaves by connecting to the server program from behind the router and noting the port number displayed in the TextBox on the server. Then disconnect and connect again. It should be the same each time.

J.A. Coutts
Attached Images
Image may be NSFW.
Clik here to view.
 
Attached Files

Viewing all articles
Browse latest Browse all 1449

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>