OpenVPN

From packets2photons
Jump to navigation Jump to search

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 presented here are adapted from: this Digital Ocean guide. There will be many similarities, the one has just included the tweaks that I needed. I have tested this with 16.04 and 18.04 and these instructions have been stable and working for a couple of years.

Install and Configure OpenVPN's Server Environment

Complete the following steps for the machine that will run OpenVPN server. For me the server was a machine running in Digital Ocean.

OpenVPN Configuration

Generally, I would recommend performing 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.

vim /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:

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

vim /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="SampleOrg"
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

If you haven't done already, make sure that you install openvpn on any clients:

sudo apt install openvpn

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:

  1. 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 wireshark 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 or 1.1.1.1 should work.