VPN

Article by on January 5, 2014

How to Setup OpenVPN

A. Setup the VPN Server

In this tutorial, we will assume you are using Ubuntu 12.04 or equivalent for your VPN server.

1. Install OpenVPN

First, install OpenVPN:

$ sudo apt-get install openvpn

2. Create Server Certificates

a. Setup Easy RSA

In this example we will use easy-rsa. So, copy the easy-rsa files to /etc/openvpn for easier access:

$ cd /etc/openvpn
$ mkdir easy-rsa
$ cp -r /usr/share/doc/openvpn/examples/easy-rsa/2.0/* ./easy-rsa/
$ cd easy-rsa
b. Configure Easy RSA

Next, configure Easy RSA. For simplicity, I'll show the lines that I changed with ellipses to show lines skipped:

$ vim vars
export KEY_SIZE=2048
...
export KEY_COUNTRY="US"
export KEY_PROVINCE="OH"
export KEY_CITY="Cincinnati"
export KEY_ORG="Joseph D. Purcell"
export KEY_NAME="Joseph D. Purcell"
export KEY_EMAIL="myemail@mail.com"
export KEY_CN="vpn.example.com"
export KEY_OU="vpn.example.com"

Now, we need to load those variables into your current session:

$ source vars

Next, if this is your first time, you will need to run clean-all which will delete the keys directory (including the index of pre-existing keys, if they exist) and create a new directory and index. In other words, don't run this if you have keys in there you still want.

$ ./clean-all
c. Create Your Certificate Authority

Next, we will create a signing key which will be used to self-sign certificates:

$ ./build-ca

Generating a 2048 bit RSA private key
.................................................................................................................+++
.+++
writing new private key to 'ca.key'
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [US]:
State or Province Name (full name) [OH]:
Locality Name (eg, city) [Cincinnati]:
Organization Name (eg, company) [Joseph D. Purcell]:
Organizational Unit Name (eg, section) [vpn.example.com]:
Common Name (eg, your name or your server's hostname) [vpn.example.com]:
Name [Joseph D. Purcell]:
Email Address [myemail@mail.com]:

Notice that Easy RSA should have pre-populated the fields for you.

d. Create Your VPN Server Certificate and Key

Next, we need to create a public certificate and private key for the VPN server. The certificate is public and is used to identify the server, but the key should be kept private.

$ ./build-key-server vpn.example.com

Generating a 2048 bit RSA private key
.........................+++
....................................................................................................+++
writing new private key to 'vpn.example.key'
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [US]:
State or Province Name (full name) [OH]:
Locality Name (eg, city) [Cincinnati]:
Organization Name (eg, company) [Joseph D. Purcell]:
Organizational Unit Name (eg, section) [vpn.example.com]:
Common Name (eg, your name or your server's hostname) [vpn.example.com]:
Name [Joseph D. Purcell]:
Email Address [josephdpurcell@gmail.com]:

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:
Using configuration from /etc/openvpn/easy-rsa/openssl.cnf
Check that the request matches the signature
Signature ok
The Subject's Distinguished Name is as follows
countryName           :PRINTABLE:'US'
stateOrProvinceName   :PRINTABLE:'OH'
localityName          :PRINTABLE:'Cincinnati'
organizationName      :PRINTABLE:'Joseph D. Purcell'
organizationalUnitName:PRINTABLE:'vpn.example.com'
commonName            :PRINTABLE:'vpn.example.com'
name                  :PRINTABLE:'Joseph D. Purcell'
emailAddress          :IA5STRING:'myemail@mail.com'
Certificate is to be certified until Jan  3 01:12:03 2024 GMT (3650 days)
Sign the certificate? [y/n]:y

1 out of 1 certificate requests certified, commit? [y/n]y
Write out database with 1 new entries
Data Base Updated
e. Create a Diffie-Hellman Key

The Diffie-Hellman key is used to establish a shared secrete between the server and the client on initial contact to encrypt key exchanges.

$ ./build-dh
Generating DH parameters, 2048 bit long safe prime, generator 2
This is going to take a long time
.............+.........................................
(many many lines of this...)
.......................................+.........++*++*
f. Copy the Keys
cp ./keys/vpn.joep-bup.key ../
cp ./keys/vpn.joep-bup.crt ../
cp ./keys/ca.crt ../
cp ./keys/dh2048.pem ../

3. Create Client Certificates

While we are at it, let's go ahead and create our certificates for the clients that will be connecting. In this example, we will just say there is only one computer called "joep-laptop".

$ ./build-key joep-laptop
Generating a 2048 bit RSA private key
.....................................................+++
...+++
writing new private key to 'joep-laptop.key'
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [US]:
State or Province Name (full name) [OH]:
Locality Name (eg, city) [Cincinnati]:
Organization Name (eg, company) [Joseph D. Purcell]:
Organizational Unit Name (eg, section) [vpn.example.com]:joep-laptop
Common Name (eg, your name or your server's hostname) [vpn.example.com]:joep-laptop
Name [Joseph D. Purcell]:
Email Address [myemail@mail.com]:

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:
Using configuration from /etc/openvpn/easy-rsa/openssl.cnf
Check that the request matches the signature
Signature ok
The Subject's Distinguished Name is as follows
countryName           :PRINTABLE:'US'
stateOrProvinceName   :PRINTABLE:'OH'
localityName          :PRINTABLE:'Cincinnati'
organizationName      :PRINTABLE:'Joseph D. Purcell'
organizationalUnitName:PRINTABLE:'joep-laptop'
commonName            :PRINTABLE:'joep-laptop'
name                  :PRINTABLE:'Joseph D. Purcell'
emailAddress          :IA5STRING:'myemail@mail.com'
Certificate is to be certified until Jan  3 01:26:02 2024 GMT (3650 days)
Sign the certificate? [y/n]:y

1 out of 1 certificate requests certified, commit? [y/n]y
Write out database with 1 new entries
Data Base Updated

Next, create a key for the "HMAC firewall" which helps block DoS attacks and UDP port flooding. This is optional, but it's easy enough to do:

$ openvpn --genkey --secret ta.key

Finally, we will copy the keys to my home directory and give me read permissions so I can copy them to my laptop later:

$ cp ca.crt /home/joep/
$ cp ta.key /home/joep/
$ cp ./keys/joep-laptop.crt /home/joep/
$ cp ./keys/joep-laptop.key /home/joep/
$ chown joep /home/joep/ca.crt
$ chown joep /home/joep/ta.key
$ chown joep /home/joep/joep-laptop.crt
$ chown joep /home/joep/joep-laptop.key

4. Configure OpenVPN

At last, let's configure OpenVPN. Copy the default config:

$ cp /usr/share/doc/openvpn/examples/sample-config-files/server.conf.gz /etc/openvpn
$ gzip -d server.conf.gz

Now, edit it; in this case I will show important lines:

$ vim server.conf
port 1194
proto udp
dev tun
ca ca.crt
cert vpn.example.com.crt
key vpn.example.com.key  # This file should be kept secret
dh dh2048.pem
server 10.8.0.0 255.255.255.0
push "redirect-gateway def1 bypass-dhcp"
tls-auth ta.key 0 # This file is secret

And, restart openvpn:

$ sudo service openvpn restart

5. Configure Networking

Here comes the tricky part. Again, assuming you want to be able to access the WAN when you connect to your VPN server you will need to configure NAT and ensure port 1194 is open.

a. Ensure Port 1194 is Open

I haven't figured out a reliable way to scan a VPN port to see if it's available. So, one way to do this is to use netcat. On a client computer open up two terminals. In the first, ssh into your VPN server and run:

$ nc -u -l 1194

Then, in the second terminal, run:

$ nc -u 192.168.0.9 1194

Now, if you put the two windows side-by-side and type something in the second terminal, you should see the same text on the server. If you do, then your port is open. If not, you need to open it.

Using ufw, you would do something like the following on your VPN server:

$ ufw allow 1194

Or, with iptables, something like:

$ iptables -I INPUT --dport 1194 -j ACCEPT

Then, use our netcat test to ensure the port is open.

b. Ensure NAT is Enabled

This is where I get lost, but I know the following worked for me. I'm using ufw so you will have to figure this out on your own if using iptables. First, edit the ufw sysctl.conf and uncomment the following line:

$ vim /etc/ufw/sysctl.conf
net/ipv4/ip_forward=1

Next, set the default forwarding policy to accept:

$ vim /etc/default/ufw
DEFAULT_FORWARD_POLICY="ACCEPT"

Finally, configure the NAT settings for the 10.8.0.0/24 subnet by adding the following lines to the end of the ufw before.rules:

$ vim /etc/ufw/before.rules
# Configure NAT settings
*nat
:POSTROUTING ACCEPT [0:0]
-A POSTROUTING -s 10.8.0.0/24 -o eth0 -j MASQUERADE
COMMIT

Now, restart ufw:

$ sudo ufw stop
$ sudo ufw start
If you are using iptables, here is a hint that may work:

$ iptables -t nat -A POSTROUTING -s 10.8.0.0/24 -o eth0 -j MASQUERADE

See Eric Hansen's article on linux.org for more details.

B. Setup the VPN Client

Finally, we can configure the VPN client (i.e. the computer connecting to the VPN server). First, we need to copy down the certificates and key from the server:

$ mkdir vpn
$ cd vpn
$ scp joep@vpn.example.com:ca.crt ./
$ scp joep@vpn.example.com:ta.key ./
$ scp joep@vpn.example.com:joep-laptop.crt ./
$ scp joep@vpn.example.com:joep-laptop.key ./

Then, be sure to go on the server and delete the copies made:

$ rm /home/joep/ca.crt
$ rm /home/joep/ta.key
$ rm /home/joep/joep-laptop.crt
$ rm /home/joep/joep-laptop.key

Okay, now I recommend using an application like Viscosity because it's easy to use. Here is an example of how to configure Viscosity:

vpn1

vpn2

vpn3

 C. Notes

If you want to connect to the VPN server but do not care to access the WAN, you can skip the entire step of enabling NAT. You also do not need push "redirect-gateway def1 bypass-dhcp" in your VPN server.cnf.

D. Further Reading

Older Articles »