Open VPN
This tutorial shows you how to setup an OpenVPN server. There are a range of online companies that can provide this service for you but there are many reasons why you, or a company, may wish to run your own OpenVPN server. The most likely reason is that your company has remote workers and these remote workers want secure access to the company's internal network services.
The instructions here are adapted from:
https://www.digitalocean.com/community/tutorials/how-to-set-up-an-openvpn-server-on-ubuntu-14-04
If you are using Ubuntu 16.04, you may wish to experiment with the updated instructions
https://www.digitalocean.com/community/tutorials/how-to-set-up-an-openvpn-server-on-ubuntu-16-04
OpenVPN is a full-featured open-source Secure Socket Layer (SSL) VPN solution that accommodates a wide range of configurations. In this tutorial, we'll set up an OpenVPN server on a Droplet and then configure access to it from Windows, OS X, iOS and Android. This tutorial will keep the installation and configuration steps as simple as possible for these setups.
Contents
Basic lab setup
The conceptual and physical lab setup is as below. Please ensure you complete the lab using the Ubuntu 16.04-ftp image.
Install and Configure OpenVPN's Server Environment
Complete the following steps for the machine that will run OpenVPN server.
OpenVPN Configuration
Generally, it is best to perform all operations as a user unless necessary and to use sudo to elevate the privileges when required. In this lab we will need to be root for almost everything so save yourself some time and:
sudo su
To become the root user permanently. Now update Ubuntu's repository lists.
apt update
Then we can install OpenVPN and Easy-RSA. Do this on the client and the server.
apt install openvpn easy-rsa
The example VPN server configuration file needs to be extracted to /etc/openvpn so we can incorporate it into our setup. This can be done with one command, you should temporarily become root for this:
gunzip -c /usr/share/doc/openvpn/examples/sample-config-files/server.conf.gz > /etc/openvpn/server.conf
Once extracted, open server.conf in a text editor.
nano /etc/openvpn/server.conf
There are several changes to make in this file. Find:
;push "redirect-gateway def1 bypass-dhcp"
Uncomment push "redirect-gateway def1 bypass-dhcp" so the VPN server passes on clients' web traffic to its destination. It should look like:
push "redirect-gateway def1 bypass-dhcp"
The next edit is:
;push "dhcp-option DNS 208.67.222.222" ;push "dhcp-option DNS 208.67.220.220"
Uncomment push "dhcp-option DNS 208.67.222.222" and push "dhcp-option DNS 208.67.220.220". It should look like:
push "dhcp-option DNS 208.67.222.222" push "dhcp-option DNS 208.67.220.220"
This tells the server to push OpenDNS to connected clients for DNS resolution where possible. This can help prevent DNS requests from leaking outside the VPN connection. However, it's important to specify desired DNS resolvers in client devices as well. Though OpenDNS is the default used by OpenVPN, you can use whichever DNS services you prefer.
The last area to change is:
;user nobody ;group nogroup
Uncomment both user nobody and group nogroup so it looks like:
user nobody group nogroup
By default, OpenVPN runs as the root user and thus has full root access to the system. We'll instead confine OpenVPN to the user nobody and group nogroup. This is an unprivileged user with no default login capabilities, often reserved for running untrusted applications like web-facing servers.
Now save your changes and exit.
Packet Forwarding
This is a sysctl setting which tells the server's kernel to forward traffic from client devices out to the Internet. Otherwise, the traffic will stop at the server. Enable packet forwarding during runtime by entering this command:
sudo su root echo 1 > /proc/sys/net/ipv4/ip_forward exit
We need to make this permanent so the server still forwards traffic after rebooting. Packet Forwarding
nano /etc/sysctl.conf
Near the top of the sysctl, uncomment the line:
#net.ipv4.ip_forward=1
It should look like:
net.ipv4.ip_forward=1
Save and exit
Uncomplicated Firewall (ufw)
ufw is a front-end for iptables and setting up ufw is not hard. It's included by default in Ubuntu 14.04, so we only need to make a few rules and configuration edits, then switch the firewall on. As a reference for more uses for ufw, see How To Setup a Firewall with UFW on an Ubuntu and Debian Cloud Server.
First set ufw to allow SSH. In the command prompt, ENTER:
ufw allow ssh
This tutorial will use OpenVPN over UDP, so ufw must also allow UDP traffic over port 1194.
ufw allow 1194/udp
The ufw forwarding policy needs to be set as well. We'll do this in ufw's primary configuration file.
nano /etc/default/ufw
Look for DEFAULT_FORWARD_POLICY="DROP". This must be changed from DROP to ACCEPT. It should look like this when done:
DEFAULT_FORWARD_POLICY="ACCEPT"
Next we will add additional ufw rules for network address translation and IP masquerading of connected clients.
nano /etc/ufw/before.rules
Make the top of your before.rules file look like below. The area in bold for OPENVPN RULES must be added. Please ensure that you change [interfacename] to the publically accessible interface. For me it was eth0.
# # rules.before # # Rules that should be run before the ufw command line added rules. Custom # rules should be added to one of these chains: # ufw-before-input # ufw-before-output # ufw-before-forward # # START OPENVPN RULES # NAT table rules *nat :POSTROUTING ACCEPT [0:0] # Allow traffic from OpenVPN client to eth0 -A POSTROUTING -s 10.8.0.0/8 -o [interfacename] -j MASQUERADE COMMIT # END OPENVPN RULES # Don't delete these required lines, otherwise there will be errors
With the changes made to ufw, we can now enable it. Enter into the command prompt:
ufw enable
Enabling ufw will return the following:
Firewall is active and enabled on system startup
To check ufw's primary firewall rules:
ufw status
The status command should return these entries:
Status: active To Action From -- ------ ---- 22 ALLOW Anywhere 1194/udp ALLOW Anywhere 22 (v6) ALLOW Anywhere (v6) 1194/udp (v6) ALLOW Anywhere (v6)
Creating a Certificate Authority and Server-Side Certificate & Key
OpenVPN uses certificates to encrypt traffic.
Configure and Build the Certificate Authority
It is now time to set up our own Certificate Authority (CA) and generate a certificate and key for the OpenVPN server. OpenVPN supports bidirectional authentication based on certificates, meaning that the client must authenticate the server certificate and the server must authenticate the client certificate before mutual trust is established. We will use Easy RSA's scripts we copied earlier to do this.
First copy over the Easy-RSA generation scripts.
cp -r /usr/share/easy-rsa/ /etc/openvpn
Then make the key storage directory.
mkdir /etc/openvpn/easy-rsa/keys
Easy-RSA has a variables file we can edit to create certificates exclusive to our person, business, or whatever entity we choose. This information is copied to the certificates and keys, and will help identify the keys later.
nano /etc/openvpn/easy-rsa/vars
The variables below should be changed according to your preference.
export KEY_COUNTRY="AU" export KEY_PROVINCE="WA" export KEY_CITY="Perth" export KEY_ORG="Mudrocks" export KEY_EMAIL="testcase@testcase.com" export KEY_OU="EpicOrganisationalUnit"
In the same vars file, also edit this one line shown below. For simplicity, we will use server as the key name. If you want to use a different name, you would also need to update the OpenVPN configuration files that reference server.key and server.crt.
export KEY_NAME="server"
Finally, find the following line the line that reads:
export KEY_CONFIG=blah blah
and change to:
export KEY_CONFIG=$EASY_RSA/openssl-1.0.0.cnf
Save and exit the file. We now need to generate the Diffie-Hellman parameters; this can take several minutes.
openssl dhparam -out /etc/openvpn/dh2048.pem 2048
Now let's change directories so that we're working directly out of where we moved Easy-RSA's scripts to earlier in Step 2.
cd /etc/openvpn/easy-rsa
Initialize the PKI (Public Key Infrastructure). Pay attention to the dot (.) and space in front of ./vars command. That signifies the current working directory (source).
. ./vars
Then
./clean-all
then
./build-ca
Simply press ENTER to pass through each prompt. If something must be changed, you can do that from within the prompt.
Generate a Certificate and Key for the Server
Still working from /etc/openvpn/easy-rsa, now enter the command to build the server's key. Wherever you see server is the export KEY_NAME variable we set in Easy-RSA's vars file earlier in Step 2.
./build-key-server server
Similar output is generated as when we ran ./build-ca, and you can again press ENTER to confirm each line of the Distinguished Name. However, this time there are two additional prompts:
Please enter the following 'extra' attributes to be sent with your certificate request A challenge password []: An optional company name []: Both should be left blank, so just press ENTER to pass through each one.
Two additional queries at the end require a positive (y) response. The last prompt above should complete with:
Write out database with 1 new entries Data Base Updated
Also, generate your ta key with:
openvpn --genkey --secret /etc/openvpn/ta.key
cp /etc/openvpn/ta.key /etc/openvpn/easy-rsa/keys/
Then copy it to where the other keys are located:
Move the Server Certificates and Keys
OpenVPN expects to see the server's CA, certificate and key in /etc/openvpn. Let's copy them into the proper location.
cp /etc/openvpn/easy-rsa/keys/{server.crt,server.key,ca.crt,ta.key} /etc/openvpn
You can verify the copy was successful with:
ls /etc/openvpn
You should see the certificate and key files for the server.
At this point, the OpenVPN server is ready to go. Start it and check the status.
service openvpn start service openvpn status
Congratulations! Your OpenVPN server should be operational. If the status message says the VPN is not running, then do a:
tail -f /var/log/syslog
Options error: --key fails with 'server.key': No such file or directory That error indicates server.key was not copied to /etc/openvpn correctly. Re-copy the file and try again.
Generate Certificates and Keys for Clients
So far we've installed and configured the OpenVPN server, created a Certificate Authority, and created the server's own certificate and key. In this step, we use the server's CA to generate certificates and keys for each client device which will be connecting to the VPN. These files will later be installed onto the client devices such as a laptop or smartphone.
Key and Certificate Building
It's ideal for each client connecting to the VPN to have its own unique certificate and key. This is preferable to generating one general certificate and key to use among all client devices.
Note: By default, OpenVPN does not allow simultaneous connections to the server from clients using the same certificate and key. (See duplicate-cn in /etc/openvpn/server.conf.)
To create separate authentication credentials for each device you intend to connect to the VPN, you should complete this step for each device, but change the name client1 below to something different such as client2 or iphone2. With separate credentials per device, they can later be deactivated at the server individually, if need be. The remaining examples in this tutorial will use client1 as our example client device's name.
As we did with the server's key, now we build one for our client1 example. You should still be working out of /etc/openvpn/easy-rsa.
./build-key client1
Once again, you'll be asked to change or confirm the Distinguished Name variables and these two prompts which should be left blank. Press ENTER to accept the defaults.
Sign the certificate? [y/n] y 1 out of 1 certificate requests certified, commit? [y/n] y
If the key build was successful, the output will again be:
Write out database with 1 new entries Data Base Updated
The example client configuration file should be copied to the Easy-RSA key directory too. We'll use it as a template which will be downloaded to client devices for editing. In the copy process, we are changing the name of the example file from client.conf to client.ovpn because the .ovpn file extension is what the clients will expect to use.
cp /usr/share/doc/openvpn/examples/sample-config-files/client.conf /etc/openvpn/easy-rsa/keys/client.ovpn
You can repeat this section again for each client, replacing client1 with the appropriate client name throughout.
Transferring Certificates and Keys to Client Devices
Recall from the steps above that we created the client certificates and keys, and that they are stored on the OpenVPN server in the /etc/openvpn/easy-rsa/keys directory.
For each client, we need to transfer the client certificate, key, and profile template files to a folder on our local computer or another client device.
Start by copying the two client1 files to /home/ubuntu (assuming the username is ubuntu):
cp /etc/openvpn/easy-rsa/keys/client* /home/ubuntu/ cp /etc/openvpn/easy-rsa/keys/ta.key /home/ubuntu/ cp /etc/openvpn/easy-rsa/keys/ca.crt /home/ubuntu/
While the exact applications used to accomplish this transfer will depend on your choice and device's operating system, you want the application to use SFTP (SSH file transfer protocol) or SCP (Secure Copy) on the backend. This will transport your client's VPN authentication files over an encrypted connection.
Here is an example SCP command using our client1 example. It places the file client1.key into the Downloads directory on the local computer.
scp your-server-ip:/home/murdoch/* Downloads/
If this fails, you may not have the openssh-server installed so install it with:
sudo apt install openssh-server
Make sure that you have the permissions to read the files from the destination.
At the end of this section, make sure you have these four files on your client device:
client1.crt client1.key client.ovpn ca.crt
Open client.ovpn and read the configuration parameters. Ensure that the client1.crt, client1.key and ca.crt match the names of those files in the folder. It is VERY likely that these will not match so please check.
Then find the following:
# You can have multiple remote entries # to load balance between the servers. remote my-server-1 1194
And change to:
remote [OpenVPNIPAddress] 1194
Next, find the area shown below and uncomment user nobody and group nogroup,It should look like this, when done:
- Downgrade privileges after initialization (non-Windows only)
user nobody group nogroup
Finally ensure that following line is uncommented:
tls-auth ta.key 1
Testing
You should now be able to connect from your client to your server by running
sudo openvpn --config client.ovpn
Watch the connection and disconnection process in Wireshark. I found that, initially, I needed to stop and start the OpenVPN server with a:
systemctl stop openvpn@server systemctl start openvpn@server
If you are having problems please debug using:
systemctl status openvpn@server
Do a:
ifconfig
You should notice that you now have a tun0 interface. You should be able to ping your servers tunnel at 10.8.0.1. Watch the traffic in wirshark to ensure that your pings are being encrypted.
If you capture on the physical interface then you should see OpenVPN Encrypted traffic. If you capture on the tun0 interface you will see unencrypted traffic. Explained here:
http://askubuntu.com/questions/29836/wireshark-showing-no-encryption-in-openvpn
Test your internet access at this point. If you are having connectivity troubles, but you can successfully set up the tunnel, then double check the ufw configuration. You may also need to check the contents of:
/etc/resolv.conf
Ensure this is pointing at a valid name server. Using 8.8.8.8 should work.
Reflection
- How does OpenVPN differ from PPTP?
- What encryption algorithms are used?
- What does the CA file do?
- How does authentication differ?
- Why do ISPs connect broadband customers using PPPoE rather than PPTP or OpenVPN
Challenge
Try to get OpenVPN working on your own personal device: Windows, OSX, iOS, Android