A rusty padlock It’s clear that using wifi access points I don’t own is an increasingly risky proposition, and given I’m going to be using others’ wifi more soon, I wanted to put together some kind of VPN to help protect my network comms. Since I want all network comms to be routed through the VPN to a trusted access point, popular methods using Hamachi didn’t seem to go far enough. A VPN would make an interesting reason to get a Raspberry Pi, but I have an older laptop laying idle.

A lightweight Linux distro and OpenVPN server, and the Tunnelblick OSX OpenVPN client made setting up a VPN tunnel a fairly straightforward system to build and manage (after working through a couple of issues that would be obvious to a networking pro). With configuration of a DynDNS hostname, port forwarding on my home wireless router, and a little networking black magic, I now have give secure access to my home network and internet connection from anywhere in the world.

I found plenty of well-written resources online for getting OpenVPN installed and running, but nothing quite fit my need to build a VPN to my home network internet connection. I don’t know that this post reflects the best way to do what I wanted to do, but I hope if you are after a similar setup it will save you some time digging.


Desired Goal

When I’m working on an untrusted wireless network, I want to be able to flick a switch on my laptop and route all network traffic through an encrypted tunnel back to my home network connection. I might also want to access file resources on machines at home, but my primary goal is to secure my network comms whilst away from home.

To do this, I need to build a VPN, on the server end of which needs to be a network bridge to to my home network (and internet connection).

I have full access to all machines involved, and I’m willing to securely pre-share keys.

Steps

  1. Clean build of a new server machine
  2. Basic point-to-point OpenVPN
  3. Configuring a network bridge
  4. Hardening

Step 1. Build a clean server

I installed Lubuntu on an older laptop (500MB RAM). As one would expect, there were no issues during installation, and performance once it was installed isn’t too bad. If I were more serious about this I would install a pure server OS without X, but I was just after some point-and-click quick wins.

I installed few extra packages, only notably the SSH server, which I then configured to only allow key-based logins. In /etc/ssh/sshd_config, ensure the following config values are set:

RSAAuthentication yes
PubkeyAuthentication yes
ChallengeResponseAuthentication no
PasswordAuthentication no
UsePAM no

Step 2. Basic OpenVPN setup

OpenVPN Server

Installing OpenVPN on this Ubuntu-based OS was as simple as apt-get install openvpn, and basic configuration is well-explained on the Ubuntu site. One small difference I encountered from the instructions was the location of the easy-rsa CA utilities – they are now on GitHub.

OSX Client

Tunnelblick is what I came across to run the client part of the VPN. It’s just a thin wrapper over the OpenVPN client configuration file, and those config files are not avoidable, but it does make starting and stopping the VPN easy.

Tunnelblick’s instructions are straightforward to follow; in fact, once installed it basically walks you through where it wants configuration files and keys copied and edited. I just SCP’d the client keys generated by the CA scripts back to my laptop, dropped them into the right place, and made the minor adjustments to config file per the Tunnelblick docs and comments in the config file itself.

Router and DNS

My wireless router happens to have an option for a DynDNS account. DynDNS don’t do a free dynamic DNS service any more, but a little google research turned me up something useful.

I configured my router with the DynDNS account info, set my VPN server to be allocated a particular IP address from the DHCP pool, and set up UDP port 1194 (OpenVPN) and TCP port 22 (SSH) to be forwarded to the VPN machine. After this, connecting to the machine via SSH worked right away.

I then reconfigured my client configuration in Tunnelblick to connect to the VPN at my new dynamic dns hostname. That too worked without fault.

Step 3. Networking

Thinking I was done at this point, a wrinkle emerged the first time I was testing away from home: by default, only resources on the private network are routed through the VPN. I wanted all network traffic from my laptop to go through the VPN.

I spotted this when I tried verifying my IP address had changed once connected to the VPN. Reloading TraceMyIP in a browser once connected didn’t show me any change. Looking at the Tunnelblick configuration, there’s a checkbox to force all traffic through the VPN and this checkbox isn’t checked by default.

Basically all I needed to do was set up IP masquerading on the VPN server. After some lost time spent looking into setting up a network bridge, I found that just a couple of commands got me going (albeit temporarily). sudo sysctl -w net.ipv4.ip_forward=1 enables IP forwarding, and sudo iptables -t nat -A POSTROUTING -s 10.8.0.0/24 -o eth0 -j MASQUERADE sets up IP masquerading on my NIC of choice. Make sure the IP address and netmask matches what is set in /etc/openvpn/server.conf; I have

server 10.8.0.0 255.255.255.0

I also added a configuration option to the /etc/openvpn/server.conf to make clients push all traffic through the VPN:

push "redirect-gateway def1"

After doing these couple of steps, I was able to connect to the VPN and see my external IP address was that assigned to my home network.

Persistent network configuration

Now I needed to make the networking changes permanent.

In /etc/sysctl.conf, add the line

net.ipv4.ip_forward=1

to enable IP forwarding.

Exactly per this page with iptables info, I set up a couple of simple networking startup and shutdown scripts to save any changes to the firewall configuration:

/etc/network/if-pre-up.d/iptablesload:

#!/bin/sh
iptables-restore < /etc/iptables.rules
exit 0

/etc/network/if-post-down.d/iptablessave:

#!/bin/sh
iptables-save -c > /etc/iptables.rules
if [ -f /etc/iptables.downrules ]; then
  iptables-restore < /etc/iptables.downrules
fi
exit 0

Remember to make the scripts executable.

Since I hadn’t restarted since making the temporary iptables change, on server shutdown and restart I verified the IP masquerade settings were still in effect (run sudo iptables-save -c to see the active settings), and that they were described in /etc/iptables.rules.


I hope my fumblings through this might help you set up your own VPN. Let me know if you want any clarification on any of the whats or hows.

Image credit: http://www.colourbox.com/preview/1928550-192532-rusty-padlock-on-an-old-metal-door.jpg

Comments