Cheat sheet: Establishing a VPN tunnel between 2 linux servers

Do you need your servers to communicate securely through the WAN or an unsecured LAN? Having some services communicating insecurely that you want to encapsulate in a VPN tunnel? Let’s see how we can have a setup using 2 servers. We could have more but… let’s keep it simple for now.

General configuration

Before we start, let’s name those 2 linux servers (here Ubuntu 14.04) which will be inter-connected via a VPN:

Server1 will play the role of the VPN server. If we would have a setup involving more than 2 servers, all of them would connect to Server1 to establish the VPN tunnel.

Server2 = the Client server (the server which will connect to Server1)

First we must install on Server1 the OpenVPN and a tool to ease the PKI configuration (we’ll create a Public Key Infrastructure Using the easy-rsa scripts):

apt-get install openvpn easy-rsa

We create a sample VPN server configuration:

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. We have many things to change out there.

At first we need to change the Diffie hellman parameters to get a better security level.
Change this:

dh dh1024.pem

to this:

dh dh2048.pem

This will double the RSA key length used when generating server and client keys.
Then uncomment those lines:

user nobody
group nogroup

By default, openVPN runs as root. We don’t need that. Better to confine openVPN in a non privilege user.
A good thing to do also is to avoid DNS requests leaking outside the VPN connexion. For this we need to declare DNS servers into our conf file (usually the ones provided by a secure DNS provider like opendns.com). If you will use the VPN for internal services, you don’t need to do that. Rely on what’s declared into /etc/hosts.
The addresses below refers to the public DNS servers provided by opendns.com:

push "dhcp-option DNS 208.67.222.222"
push "dhcp-option DNS 208.67.220.220"

This is not our goal here but if we were about to create a VPN gateway, we would need those extra steps:

  • setup the VPN server to pass the traffic thru
  • enable the IP forwarding
  • setup a firewall like ufw (Uncomplicated Firewall) to protect the VPN server

To pass thru the VPN connexion, uncomment the below line.
N.B.: we don’t need that for our 2 servers to communicate.

push "redirect-gateway def1 bypass-dhcp"

Again, the following is only needed in case you setup a VPN gateway. In that case you need the VPN server to forward internet requests from clients to the internet with enabling packet forwarding at the kernel level. If we don’t do that, the traffic will stop at the server.

echo 1 > /proc/sys/net/ipv4/ip_forward

We just enabled it. But it will return to default (disabled) after reboot. To make it permanent, edit /etc/sysctl.conf and uncomment the next line to enable packet forwarding for IPv4

net.ipv4.ip_forward=1

To setup the Firewall you will find a good article on ufw here.

Voila. We finished with the first part of the configuration.

Creating a Certificate Authority and Server-Side Certificate & Key

Our OpenVPN configuration will use certificates to encrypt traffic. More practical and secure than using passwords.

Configure and Build the Certificate Authority

First we need to copy the RSA generation scripts:

cp -r /usr/share/easy-rsa/ /etc/openvpn

We make a key storage place:

mkdir /etc/openvpn/easy-rsa/keys

Now edit /etc/openvpn/easy-rsa/vars and adapt it to your business. This is what you should change:

# These are the default values for fields
# which will be placed in the certificate.
# Don't leave any of these fields blank.
export KEY_COUNTRY="US"
export KEY_PROVINCE="CA"
export KEY_CITY="SanFrancisco"
export KEY_ORG="Fort-Funston"
export KEY_EMAIL="me@myhost.mydomain"
export KEY_OU="MyOrganizationalUnit"

Change also the key name:

# X509 Subject Field
export KEY_NAME="EasyRSA"

After that, we need to generate the Diffie-Hellman parameters. Beware, this can take several minutes…

openssl dhparam -out /etc/openvpn/dh2048.pem 2048

Now, let’s initialise the PKI (beware of the double . in front of /vars).
This last command builds the certificate authority (CA) by invoking an interactive OpenSSL command. The output will prompt you to confirm the DN (Distinguished Name) variables that were entered earlier into the Easy-RSA’s variable file (country name, organisation, etc.). When building the CA, simply press ENTER to pass through each prompt:

cd /etc/openvpn/easy-rsa
. ./vars
./clean-all
./build-ca

Generate a Certificate and Key for the Server

Press ENTER the whole way. Unless it asks for y/n. Answer y.

./build-key-server server

The output should finish with:

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

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} /etc/openvpn

Voila! OpenVPN server is ready to go. Start it and check the status:

service openvpn start
service openvpn status

The status command should return: “VPN ‘server’ is running”.

Generate Certificates and Keys for client server

As stated before, our client server name is server2 (we’ll need to repeat this procedure for each client server):

./build-key server2

Again press ENTER the whole way. Unless it asks for y/n. Answer y.

The example client configuration file should be copied to the Easy-RSA key directory. We’ll use it as a template which will be downloaded to client servers for editing. We need to change the name of the example file from client.conf to client.ovpn because the .ovpn file extension is what the clients will expect to have.

cp /usr/share/doc/openvpn/examples/sample-config-files/client.conf /etc/openvpn/easy-rsa/keys/client.ovpn

Creating the unified profile

Our client server will need those files transfered to him:

/etc/openvpn/easy-rsa/keys/server2.crt
/etc/openvpn/easy-rsa/keys/server2.key
/etc/openvpn/easy-rsa/keys/client.ovpn (the same for all clients)
/etc/openvpn/ca.crt (the same for all clients)

Some files are specific to each client, some others are the same for all.
The easiest way to transfer all what the server client needs, is to create a unified profile. It’s a file (we’ll named it  client.ovpn) containing all the infos available in all the above mentioned files.

First, let’s edit this file: /etc/openvpn/easy-rsa/keys/client.ovpn.
Change here the IP and name to match your VPN server (server1):

# The hostname/IP and port of the server.
# You can have multiple remote entries
# to load balance between the servers.
remote server1 1194
;remote my-server-2 1194

As for the server uncomment this:

# Downgrade privileges after initialization (non-Windows only)
user nobody
group nogroup

As we’ll include all the client’s files in the client.ovpn file, we need to comment those lines:

# SSL/TLS parms.
# See the server config file for more
# description. It's best to use
# a separate .crt/.key file pair
# for each client. A single ca
# file can be used for all clients.
#ca ca.crt
#cert client.crt
#key client.key

To include the client’s files into this one unified profile, the contents of the ca.crt, server2.crt, and server2.key files are pasted directly into it using a basic XML-like syntax.
First create this structure at the end of the client.ovpn file and insert the mentioned files in between tags:

<ca>
(insert ca.crt here)
</ca>
<cert>
(insert client1.crt here)
</cert>
<key>
(insert client1.key here)
</key>

On the client server side

First, you need to SCP the client.ovpn file from server1 to the client server server2.
Then on server2 we install OpenVPN:

apt-get install openvpn

Now, move the file client.ovpn to /etc/openvpn and rename it into .conf :

cp client.ovpn /etc/openvpn/client.conf

Renaming into .conf will make the VPN connection to server1 to start at boot time automatically.

You can start it manually running:

openvpn --config /etc/openvpn/client.conf

Voila. You should now see on server2 a new interface used for the VPN:

tun0 Link encap:UNSPEC HWaddr 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00 
inet addr:10.8.0.6 P-t-P:10.8.0.5 Mask:255.255.255.255
UP POINTOPOINT RUNNING NOARP MULTICAST MTU:1500 Metric:1
RX packets:3 errors:0 dropped:0 overruns:0 frame:0
TX packets:3 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:100 
RX bytes:252 (252.0 B) TX bytes:252 (252.0 B)

Same on server1:

tun0 Link encap:UNSPEC HWaddr 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00 
inet addr:10.8.0.1 P-t-P:10.8.0.2 Mask:255.255.255.255
UP POINTOPOINT RUNNING NOARP MULTICAST MTU:1500 Metric:1
RX packets:3 errors:0 dropped:0 overruns:0 frame:0
TX packets:3 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:100 
RX bytes:252 (252.0 B) TX bytes:252 (252.0 B)

Reboot server2. The connection should go up again without your intervention.

Bravo! You have now 2 servers connected to each other via a VPN tunnel 🙂

Share the Post:

Related Posts