July 22, 2016 - Tom Hacohen

How to Use an External Server with OpenVPN to Escape NATs

I have recently moved to a new flat and I love it, though unfortunately not all is perfect. One might expect central London (literally 500m away from the actual geographical centre) to have the best internet connection London has to offer. Well, one would be wrong; I am no longer able to get anything better than lousy ADSL2+, and this amazing offering comes with a high price, a long contract, and a month’s wait for the installation. This has led me to choose a 4G internet provider; the connection is usually better than what I would have expected to get with any of the landline providers, is much cheaper, and I had it up and running less than 24hrs after I joined.

However, there is a problem with this: the 4G provider uses a carrier-grade NAT, that made impossible to access my home server from outside my home network. Luckily, I have a VPS that is not behind a NAT so the solution was obvious: tunnel everything through it.

The Solution

One easy solution to my problem could be to run a VPN, connect my home server to it, and then connect to the VPN every time I want to access my home server. This solution works, but it’s annoying to connect to the VPN every time and even more annoying to give VPN access to anyone who needs access to my private Git server. This led to me choosing a slightly more complex solution that solves this issue: forward specific ports from a VPN that has a unique external IP address to my home server.

Setup OpenVPN

From now on I’ll call the externally available server EXT and the one I’ll expose HOME. First, it’s necessary to setup an OpenVPN server on EXT, however, setting up OpenVPN is beyond the scope of this post. I recommend following the Arch Linux guide, and the OpenVPN official documentation.

With that being said, there are a few important OpenVPN configurations you should make sure to have in your OpenVPN server (EXT):

At this point you should make sure you can connect to the VPN and access services running on HOME from EXT.

Setup Port Forwarding

The first thing to do when setting up port forwarding, is to enable it in the kernel (on EXT). Sadly, since we still live in an IPv4 world (this is why we have CGNAT in the first place), I’ll only deal with the IPv4 case.

As root:

The last step is to tell iptables which ports should be forwarded.  For the sake of the example, I’ll forward TCP port 2222 for ssh and UDP ports 61001-62000 for Mosh. The first step is to check HOME’s ip address using the command ip addr show.

Then, complete the following commands as root, for this example HOME’s ip address is

Important note: commands like sysctl and iptables only last until the next boot, so don’t forget to make them persistent in whatever way is recommended for your distribution.

Verify Functionality

Connect to a network different than the one your home server is on, and try to connect to ssh using port 2222 with EXT’s ip/hostname. For example:

You should now be successfully logged into HOME.

One Additional Trick

One annoyance that comes with this method is that all traffic to HOME is passed through EXT, even if the user’s device has direct access to HOME by being on the same LAN. This is due to the fact that the DNS name and ip address you are now using to connect to HOME is actually EXT’s.

One simple solution is to use a different domain name depending on whether or not the device has direct access. This is awfully annoying, especially when using git.

The better solution I chose for my setup is to configure DNS to resolve differently inside my home network, many routers support configuration for this. So for example, I use git.stosb.com for my git server. The public DNS is a CNAME to stosb.com, but inside my network, it resolves to HOME’s local address, which means everything will just connect to it directly.

Final Notes

I would love to hear if you have any corrections or better ideas on how to implement this. I would especially love to hear if you have any comments on how to harden this setup even further. I have a feeling the iptables rules could be a bit more strict. Please let me know.

This article was originally posted on Tom’s personal blog, and has been approved to be posted here.

Tom Hacohen

About Tom Hacohen

Tom has been using Linux since 2003. Previously a core developer and part of the leading team at SHR (Openmoko), he is currently a core developer for the EFL (www.enlightenment.org). He has also contributed to many other Open Source projects over the years. In 2010 he started working at Samsung's open source group on the Tizen Linux platform.

Image Credits: Bruno Girin

General / Linux / Open Source Infrastructure nat / openvpn / port forwarding / vpn /

Leave a Reply

Your email address will not be published. Required fields are marked *

Comments Protected by WP-SpamShield Anti-Spam