“All I want for Christmas is my own VPN…my own VPN, my own VPN” – Dustin

I’ve been wanting to have access to my own secure VPN for quite some time so that when I’m away from home and only have access to insecure networks, I don’t have to use work’s VPN for personal use or worry about someone intercepting my traffic. I looked into a couple paid VPN solutions but none of them seem to guarantee your privacy as far as I’m concerned. I figured my best option was to setup and manage my own.

I chose to do all my setup on Ubuntu Linux but you can easily port these instructions to an alternative Linux distribution with relative ease.

Just a quick heads up before we dive in. This article is the first part of a two-part article on setting up your own VPN solution. In the first part, I show you how to set up an SSL VPN. The second part of the article (coming soon) will detail how to set up your own IPSEC VPN.

Creating your own SSL VPN using OpenVPN

An SSL VPN is generally all you’ll need for a secure VPN solution unless you want to use other devices that don’t support SSL VPNs, like an iPad, iPhone, or iPod Touch (see the second part of the article – coming soon).

Start by installing OpenVPN and DNSMasq for local DNS resolution

nobody@nobody:~/$ sudo apt-get install openvpn dnsmasq

OpenVPN comes with a bunch of scripts called easy-rsa that make generating your keys and certificates painless. We are going to make some local modifications to the scripts so it’s best to copy them into the /etc/openvpn directory

nobody@nobody:~/$ sudo cp -R  
> /usr/share/doc/openvpn/examples/easy-rsa/ /etc/openvpn

After copying, open this file

nobody@nobody:/etc/openvpn/easy-rsa/2.0$ sudo vi vars

and modify these values at the very end of the file, replacing YOUR_* with your information.

# These are the default values for fields
# which will be placed in the certificate.
# Don't leave any of these fields blank.

Now, load the values you just entered into your shell environment by ‘sourcing’ the vars file

nobody@nobody:/etc/openvpn/easy-rsa/2.0$ source vars

Next, generate the keys for the Certificate Authority (CA) – this is the certificate that will sign all certificates (client and server). If the above step worked properly you should just be able to press enter at each prompt except for the common name. For the common name, put “server-ca”.

nobody@nobody:/etc/openvpn/easy-rsa/2.0$ sudo ./build-ca

Now that we have the CA, we can create the keys for the client and the server. To create the server key, run the following. You’ll be prompted like last time where you can hit enter for everything except the common name. This time, for the common name, put “server”

nobody@nobody:/etc/openvpn/easy-rsa/2.0$ sudo 
> ./build-server-key server

For each client you have that will use the VPN, run this command, replacing “YOUR_CLIENT” with the name of the client

nobody@nobody:/etc/openvpn/easy-rsa/2.0$ sudo 
> ./build-key YOUR_CLIENT

As an extra security measure, we can generate a static key that will be required during SSL/TLS handshaking. Essentially what this does is it makes it so that unless a client uses this key during handshaking, OpenVPN will completely ignore the packet. To keep all of our keys in the same place, make sure you run this in the keys/ directory

nobody@nobody:/etc/openvpn/easy-rsa/2.0/keys$ sudo 
> openvpn --genkey --secret ta.key

One more script to run: the script to generate the Diffie-Hellman parameters. If you’re wondering what Diffie-Hellman is, it’s a secure method for the initial key exchange between the client and the server on an unsecured channel before the VPN is established.

nobody@nobody:/etc/openvpn/easy-rsa/2.0$ sudo ./build-dh

If you want to verify that you’ve done everything correctly up to this point, your /etc/openvpn/easy-rsa/2.0/keys directory should contain at least these files where “YOUR_CLIENT” has been replaced with what you used above for the client(s) name(s).

-rw-r--r-- 1 root root 1338 Dec 20 20:53 ca.crt
-rw------- 1 root root  887 Dec 20 20:53 ca.key
-rw-r--r-- 1 root root  245 Dec 20 20:57 dh1024.pem
-rw-r--r-- 1 root root 3918 Dec 20 20:57 YOUR_CLIENT.crt
-rw-r--r-- 1 root root  696 Dec 20 20:56 YOUR_CLIENT.csr
-rw------- 1 root root  887 Dec 20 20:56 YOUR_CLIENT.key
-rw-r--r-- 1 root root 4070 Dec 20 20:55 server.crt
-rw-r--r-- 1 root root  716 Dec 20 20:55 server.csr
-rw------- 1 root root  887 Dec 20 20:55 server.key
-rw------- 1 root root  636 Dec 20 20:56 ta.key

Copy the necessary keys we just created to /etc/openvpn so they can be used

nobody@nobody:/etc/openvpn/easy-rsa/2.0/keys$ sudo cp 
> ca.crt ca.key server.crt server.key dh1024.pem ta.key /etc/openvpn

Now that we are done generating keys and certificates, we have to create the ‘server.conf’ and ‘client.conf’ files for the client and server to read respectively. OpenVPN comes with a number of example configurations and it’s easiest to just start from there.

nobody@nobody:$ sudo cp 
> /usr/share/doc/openvpn/examples/sample-config-files/server.conf
> /usr/share/doc/openvpn/examples/sample-config-files/client.conf
> /etc/openvpn

Open server.conf and add the following lines

nobody@nobody:/etc/openvpn/$ sudo vi server.conf
# Enables traffic to be tunneled through the VPN
push "redirect-gateway def1"
# Sets the DNS server for VPN clients
push "dhcp-option DNS"
# TLS Auth key, drop ALL packets that don't HMAC with this key
# during handshake
tls-auth ta.key 0
# Use AES 256 bit key size with Cipher Block Chaining mode
cipher AES-256-CBC
# Drop privileges of the VPN service after its running
user nobody
group nogroup

Next, edit the client.conf, and edit and/or add these lines, replacing “YOUR_SERVER_ADDRESS” and “YOUR_CLIENT” with your values.

nobody@nobody:/etc/openvpn/$ sudo vi client.conf
# The address of the VPN server
# Downgrade priveleges
user nobody
group nogroup
# The name of the client key and cert
cert YOUR_CLIENT.crt
# The key to use during TLS/SSL handshaking
tls-auth ta.key 1
# Use AES 256 bit key size with Cipher Block Chaining mode
cipher AES-256-CBC

We’re now done with all of the OpenVPN settings but we need to tweak a few OS settings.

We have to turn off ICMP accept and send redirects and enable IP forwarding. You can do this by editing the /etc/sysctl.conf file and adding the following at the end of the file

nobody@nobody:~/$ sudo vi /etc/sysctl.conf

Now we need to add a few rules in iptables. You have to add them to a boot script so they’re not lost on reboot

nobody@nobody:~/$ sudo vi /etc/rc.local
# Use the 'state' module to ACCEPT RELATED or ESTABLISHED FORWARDed 
# connections
iptables -A FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT
# ACCEPT FORWARDed connections
iptables -A FORWARD -s -j ACCEPT
# REJECT all other FORWARDed connections
iptables -A FORWARD -j REJECT
# MASQUERADE any VPN addresses going out 
iptables -t nat -A POSTROUTING -s -o eth0 -j MASQUERADE

That’s all for configuration!

At this point, you can restart and everything will be configured when the machine is back up. Alternatively you can run the following if you don’t want to restart

nobody@nobody:~/$ sudo sysctl -p
nobody@nobody:~/$ sudo /etc/rc.local
nobody@nobody:~/$ sudo /etc/init.d/openvpn restart

Since we generated the client(s) keys on the server to make things easier, you MUST make sure that you transfer the client(s) keys using a secure channel like SCP or SFTP! So just to make things clear, securely copy the following files to the client, replacing “YOUR_CLIENT” as always.

  • ca.crt
  • ta.key
  • client.conf

Once you have all the necessary files on the client, it’s very easy to configure the client.

Mac OS X

Download Tunnelblick and place all config files in ~/Library/openvpn


Download the OpenVPN GUI and place all config files in C:/Program Files/OpenVPN/config, renaming client.conf to client.ovpn

Happy VPN’ing! Stay tuned for the second installment of this article where I show you how to setup an IPSEC VPN that’s compatible with any native iOS device like your iPhone or iPad.