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.
nmapto figure out whitelisted ports
- Run socat to relay traffic to your VPN server
- Update your VPN client to use the relay port
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.
nmap on OSX, you can just use homebrew and run:
$ 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:
$ 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
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:
$ 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:
$ 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:
$ sudo socat UDP-LISTEN:67,fork UDP:localhost:1194
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:
From the Tunnelblick config screen, select your VPN configuration and click the gear icon, and select Edit OpenVPN Configuration File
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.
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
You can also start
socat in verbose mode so that any connection activity is output to the screen:
$ sudo socat -v UDP-LISTEN:67,fork UDP:localhost:1194