Mike Ferrier

I beat code into submission.

Using Nmap and Socat to Get Around Public Internet Port Restrictions

In a previous post, I detailed how I set up a VPN server so that I could internet securely while traveling and using public internet access points. Public internet is convenient, but is usually insecure by default, so tunnelling all your traffic through a VPN is a smart bet.

However, some public networks can be a bit restrictive with what kinds of traffic they allow. For example, when we were staying in Fukuoka we stayed at the interestingly-named Hotel Active! which, though it was a great hotel and had free internet, would only allow you to send traffic out on a few ports. I had a sneaking suspicion going in that the free internet might give me problems as I had read other reviews of this hotel chain that suggested it might be troublesome.

Not only would this mean that I couldn’t use my secure VPN, but it would also prevent me from using SSH to connect to Github and other work-related secure connections. Annoying!

Thankfully there are ways around these restrictions. If they allow any outgoing traffic on any port, then you can run a server remotely to receive that data and relay it to your VPN server. To do this, we’re going to run nmap to figure out which outgoing port we can use to connect, then we’re going to run socat on our VPN server on that port, and relay the traffic to our real VPN server.

  1. Use nmap to figure out whitelisted ports
  2. Run socat to relay traffic to your VPN server
  3. Update your VPN client to use the relay port
  4. Troubleshooting

1. Use nmap to figure out whitelisted ports

The first thing you have to do is figure out on which ports the network will allow outgoing data. For this you can use the excellent nmap security scanner. Once you’re on the restrictive network you can use it to scan a bunch of regular ports and see which ones are allowed through and which ones aren’t.

WARNING: While port scanning is an invaluable tool for debugging and troubleshooting networks, it can also raise suspicion of malicious activity. For example, port scanning for a vulnerable piece of software with the intention of exploiting it. Suspicious port scanning can get you in trouble with your ISP or network administrator, so use it sparingly and if you’re not sure if you know what you’re doing, don’t do it at all.

To install nmap on OSX, you can just use homebrew and run:

1
$ brew install nmap

Once you have nmap installed, you’re ready to start scanning.

On an unfiltered network, the results of the scan will show open and closed ports, like this example where we probe ports 75 to 85:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
$ nmap mikeferrier.com -p 75-85 -Pn --reason

Starting Nmap 6.25 ( http://nmap.org ) at 2013-07-14 14:44 EDT
PORT   STATE  SERVICE    REASON
75/tcp closed priv-dial  conn-refused
76/tcp closed deos       conn-refused
77/tcp closed priv-rje   conn-refused
78/tcp closed unknown    conn-refused
79/tcp closed finger     conn-refused
80/tcp open   http       syn-ack
81/tcp closed hosts2-ns  conn-refused
82/tcp closed xfer       conn-refused
83/tcp closed mit-ml-dev conn-refused
84/tcp closed ctf        conn-refused
85/tcp closed mit-ml-dev conn-refused

The extra argument -Pn tells nmap not to ping the host, just to scan it, and –reason prints out the reason the port state was resolved to the value shown. This will come in handy later.

However, on a filtered network you’ll usually be able to see which ports are filtered. In this example, I’ve manually filtered outgoing ports 75-80 to show what it looks like:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
$ nmap mikeferrier.com -p 75-85 -Pn --reason

Starting Nmap 6.25 ( http://nmap.org ) at 2013-07-14 14:44 EDT
PORT   STATE    SERVICE    REASON
75/tcp filtered priv-dial  no-response
76/tcp filtered deos       no-response
77/tcp filtered priv-rje   no-response
78/tcp filtered unknown    no-response
79/tcp filtered finger     no-response
80/tcp filtered http       no-response
81/tcp closed   hosts2-ns  conn-refused
82/tcp closed   xfer       conn-refused
83/tcp closed   mit-ml-dev conn-refused
84/tcp closed   ctf        conn-refused
85/tcp closed   mit-ml-dev conn-refused

You can see that nmap got “no response” from ports 75-80, and so marked them as “filtered.” Depending on how the firewall is configured, sometimes instead of “filtered” you’ll see filtered ports marked as “closed” but the reason will be “reset,” which is a different way for firewalls to deny traffic but amounts to the same thing: you can’t send traffic on those ports.

What you’re looking for here is an outgoing port that isn’t filtered, so that you can use it to send out all your tunneled VPN traffic and bypass the firewall. When I scanned from the hotel, I noticed every port from 1-100 was filtered except 53 (DNS), 67 (DHCPS), and 80 (HTTP). It looked something like this:

1
2
3
4
5
6
7
8
9
$ nmap mikeferrier.com -p 1-100 -Pn --reason

Starting Nmap 6.25 ( http://nmap.org ) at 2013-07-14 14:54 EDT
Not shown: 97 filtered ports
Reason: 97 no-response
PORT   STATE   SERVICE REASON
53/tcp closed  domain  conn-refused
67/tcp closed  dhcps   conn-refused
80/tcp open    http    syn-ack

So 97 ports were filtered, one was open (web), and two were closed, but responding as closed. This will clue you in that traffic to these ports are allowed out by the network. For my purposes, I chose port 67 to work with.

2. Run socat to relay traffic to your VPN server

socat is an excellent multipurpose relay tool. It can pretty much relay traffic from anywhere to anywhere, and so it’s the perfect choice for relaying our traffic from the unrestricted port to our VPN server. Installing socat is left as an exercise for the reader, but you need to install it on a remote server, ideally on the same server as your VPN server so that you’re relaying locally and not across the internet.

I’m using port 67 as the relay port, and my VPN server listens on UDP port 1194, so you need to configure socat to listen for UDP packets on port 67, and relay them to localhost UDP port 1194:

1
$ sudo socat UDP-LISTEN:67,fork UDP:localhost:1194

The fork directive tells socat to fork a process for each connection so that you can keep listening on port 67. Without this, socat will terminate along with the end of the first connection.

You won’t see any output from this command, but if you want to troubleshoot or verify it’s working, you can add a -v flag to make socat’s output more verbose. It’ll spit out a ton of garbage when you connect so you can tell the connection is being made.

3. Update your VPN client to use the relay port

Once this relay is set up, you’re ready to connect. You have to reconfigure your VPN client to use the new relay port, though. This is generally done either through a configuration GUI or by editing a config file.

I use the very intuitive Tunnelblick OpenVPN frontend GUI for OSX, so for me the process is:

  1. From the Tunnelblick config screen, select your VPN configuration and click the gear icon, and select Edit OpenVPN Configuration File

  2. Find where the port is specified, and switch it to your relay port:

Once that’s done and saved, connect to your VPN and you should be up and running.

4. Troubleshooting

If for some reason it doesn’t work, you can troubleshoot by running nmap on the relay port to make sure you can connect to it from your local machine:

$ sudo nmap mikeferrier.com -p 67 -sU -Pn –reason

1
2

You can also start <code>socat</code> in verbose mode so that any connection activity is output to the screen:

$ sudo socat -v UDP-LISTEN:67,fork UDP:localhost:1194 “`

Happy relaying!

Comments