Friday, 3 June 2016

Using a raspberry pi (or any Debian based computer) to set up an open VPN server

Why

There are many howto's explaining the set-up of an OpenVPN server. The majority of what I have seen, provide instructions about setting up a tunnel device. This allows you to gain access to the OpenVPN server itself, but requires a lot more customisation if you want to access other computers on the remote LAN.

Using a tap device is much easier, and allows the OpenVPN client to be able to access not only the server but all other computers connected to the same LAN.

The basic idea is that you create an Ethernet bridge on the VPN server. Each time clients connect, the server taps them to that bridge and so clients behave as if they are physically connected to the remote LAN.

How

I would advice starting your setup with a clean fresh install. Before proceeding to follow the instructions below, issue:

pi@gabriella:~ $ sudo apt-get update && sudo apt-get dist-upgrade 

Install the bridge

The first step is to set up out bridge:

pi@gabriella:~ $ sudo apt-get install bridge-utils

After the bridge-utils package is installed, we need to change the server's network configuration file in order to activate the bridge.The actual file is:/etc/network/interfaces and the definition of the bridge is :

# interfaces(5) file used by ifup(8) and ifdown(8)

# Please note that this file is written to be used with dhcpcd
# For static IP, consult /etc/dhcpcd.conf and 'man dhcpcd.conf'

# Include files from /etc/network/interfaces.d:
source-directory /etc/network/interfaces.d

auto lo
iface lo inet loopback

face eth0 inet manual

# Our bridge initially contains just the ethernet interface and is configured to use DHCP
auto br0
  iface br0 inet dhcp
  bridge_ports eth0

# You can delete these lines if you do not whish to use Wi-fi 
allow-hotplug wlan0
iface wlan0 inet manual
    wpa-conf /etc/wpa_supplicant/wpa_supplicant.conf

allow-hotplug wlan1
iface wlan1 inet manual
    wpa-conf /etc/wpa_supplicant/wpa_supplicant.conf

This setup uses DHCP for the bridge. Setting up a static IP is explained in the Network Configuration section of the Debian Wiki. The same pages provide more information and details about bridging. The actual link is here.

At this point a server reboot is required in order to verify the bridge setup. When the server is up again you can check that the bridge is working by examining the outcome of the ip addr command which should be similar to this:

pi@gabriella:/etc/openvpn $ ip addr
1: lo:  mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: eth0:  mtu 1500 qdisc pfifo_fast master br0 state UP group default qlen 1000
    link/ether b8:27:eb:b2:d8:f2 brd ff:ff:ff:ff:ff:ff
    inet 169.254.30.59/16 brd 169.254.255.255 scope global eth0
       valid_lft forever preferred_lft forever
3: br0:  mtu 1500 qdisc noqueue state UP group default qlen 1000
    link/ether b8:27:eb:b2:d8:f2 brd ff:ff:ff:ff:ff:ff
    inet 10.0.1.240/24 brd 10.0.1.255 scope global br0
       valid_lft forever preferred_lft forever
    inet 10.0.1.205/24 brd 10.0.1.255 scope global secondary br0
       valid_lft forever preferred_lft forever
    inet6 fe80::ba27:ebff:feb2:d8f2/64 scope link 
       valid_lft forever preferred_lft forever

install openvpn

With the bridge working the next step will be installation and configuration of the OpenVPN server itself. Before we proceed with the server installation we will lay out the necessary fact about the network the server is on:

  • Our network is a class C net with a broadcast address of 10.0.1.0/24
  • Default gateway is 10.0.1.1
  • Network DNS is 10.0.1.152
  • The target network uses DHCP. We have set aside the range between 10.0.1.32 and 10.0.1.39 to be used by our clients,

Having clear our theses fact we may begin our installation.

pi@gabriella:~ $ sudo apt-get install openvpn easy-rsa 

Since all the commands that we will type from now on will require root privileges, it is wise to do a :

pi@gabriella:~ $ sudo su -
root@gabriella:~# cd /etc/openvpn/
root@gabriella:/etc/openvpn#

We will create a new server configuration file. This file is /etc/openvpn/server.conf with the following contents

# --------------------------------------------------------------------------------
# OpenVPN bridging configuration file.
# Adopted from the Ubuntu Community Page at https://help.ubuntu.com/community/OpenVPN
# Date may -15th 2016
# --------------------------------------------------------------------------------
mode server
tls-server

local 10.10.1.240       ## ip/hostname of server
port 1194               ## default openvpn port
proto udp

# --------------------------------------------------------------------------------
# Bidging directive
# --------------------------------------------------------------------------------
dev tap0 

script-security 2       ## allow calling up.sh and down.sh
up "/etc/openvpn/up.sh br0 tap0 1500"
down "/etc/openvpn/down.sh br0 tap0"

persist-key
persist-tun

# --------------------------------------------------------------------------------
# certificates and encryption
# --------------------------------------------------------------------------------
ca ca.crt
cert server.crt
key server.key          # This file should be kept secret
dh dh2048.pem
tls-auth ta.key 0       # This file is secret

cipher BF-CBC           # Blowfish (default)
comp-lzo

# Allow multiple clients to connect using the same client keys
# duplicate-cn

# --------------------------------------------------------------------------------
# DHCP Information
# --------------------------------------------------------------------------------
ifconfig-pool-persist ipp.txt
# The first address is the bridge address of the server the second is the netmask to use
# and the next twoo addresses are the range that should be assigned to clients
server-bridge 10.0.1.240 255.255.255.0 10.0.1.32 10.0.1.39
push "dhcp-option DNS 10.0.1.152"
push "dhcp-option DOMAIN simsons"
max-clients 8           ## set this to the max number of clients that should be connected at a time

# --------------------------------------------------------------------------------
# log and security
# --------------------------------------------------------------------------------
user nobody
group nogroup
keepalive 10 120
status openvpn-status.log
verb 3

Next we will need to create the two scripts that hook and unhook our tap device to the server bridge. These files should be called up.sh and down.sh (These are the names in server.conf file) with the following contents.

#!/bin/sh
# File up.sh adds a device to a bridge with a specified MTU

BR=$1    # bridge to add device to
DEV=$2   # actual device to add
MTU=$3   # MTU value

/sbin/ip link set "$DEV" up promisc on mtu "$MTU"
/sbin/brctl addif $BR $DEV
and
#!/bin/sh
# file down.sh remove a device from a bridge

BR=$1
DEV=$2

/sbin/brctl delif $BR $DEV
/sbin/ip link set "$DEV" down

Do not forget, to make both scripts executable

root@gabriella:/etc/openvpn# chmod +x up.sh down.sh 

Having done all that, it's time for a break. We will create our own DH 2048 bit file.

root@gabriella:/etc/openvpn# openssl dhparam -out dh2048.pem 2048
Generating DH parameters, 2048 bit long safe prime, generator 2
This is going to take a long time
................+........................................................................................................+.........................................

Even on a four core Raspberry-PI2 model B board, this takes well over 40 minutes, so sit back and relax

Create the Certificates

With the dh2048.pem file in place, we will start creating our server and client certificates by first copying the easy-rsa scripts to our servers setup directory and next creating the folder that will host our keys.

In order to make things a bit more secure we will create an additional tls-auth directive and the related key

root@gabriella:/etc/openvpn# openvpn --genkey --secret ta.key
root@gabriella:/etc/openvpn# cp -r /usr/share/easy-rsa/ /etc/openvpn
root@gabriella:/etc/openvpn# cd easy-rsa/
root@gabriella:/etc/openvpn/easy-rsa# mkdir keys

Next step is the creation of the actual server certificates. Oprn the /etc/openvpn/easy-rsa/vars file and fill in the details accordingly.

root@gabriella:/etc/openvpn# vim /etc/openvpn/easy-rsa/vars 

Change the lines (first one is line 64 in my version) that refer to the certificate creation parameters, so they look similar to this:

# 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="gr"
export KEY_PROVINCE="Rodope"
export KEY_CITY="Komotini"
export KEY_ORG="Aryballos"
export KEY_EMAIL="admin@aryballos.gr"
export KEY_OU="Aryballos-IT-Services"

# X509 Subject Field
export KEY_NAME="server"

Save, exist, run the file ... and do a clean-all to start fresh.

root@gabriella:/etc/openvpn/easy-rsa# . ./vars 
NOTE: If you run ./clean-all, I will be doing a rm -rf on /etc/openvpn/easy-rsa/keys
root@gabriella:/etc/openvpn/easy-rsa# ./clean-all

The next command will build the required certificate authorities for the server (Hit ENTER when there is a prompt).

root@gabriella:/etc/openvpn/easy-rsa# ./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) [gr]:
State or Province Name (full name) [Rodope]:
Locality Name (eg, city) [Komotini]:
Organization Name (eg, company) [Aryballos]:
Organizational Unit Name (eg, section) [Aryballos-IT-Services]:
Common Name (eg, your name or your server's hostname) [Aryballos CA]:
Name [server]:
Email Address [admin@aryballos.gr]:
root@gabriella:/etc/openvpn/easy-rsa# 

Now it's time to build the actual server key.

root@gabriella:/etc/openvpn/easy-rsa# ./build-key-server server
Generating a 2048 bit RSA private key
.................................................................................................................................+++
....................................................+++
writing new private key to 'server.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) [gr]:
State or Province Name (full name) [Rodope]:
Locality Name (eg, city) [Komotini]:
Organization Name (eg, company) [Aryballos]:
Organizational Unit Name (eg, section) [Aryballos-IT-Services]:
Common Name (eg, your name or your server's hostname) [server]:
Name [server]:
Email Address [admin@aryballos.gr]:

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-1.0.0.cnf
Check that the request matches the signature
Signature ok
The Subject's Distinguished Name is as follows
countryName           :PRINTABLE:'gr'
stateOrProvinceName   :PRINTABLE:'Rodope'
localityName          :PRINTABLE:'Komotini'
organizationName      :PRINTABLE:'Aryballos'
organizationalUnitName:PRINTABLE:'Aryballos-IT-Services'
commonName            :PRINTABLE:'server'
name                  :PRINTABLE:'server'
emailAddress          :IA5STRING:'admin@aryballos.gr'
Certificate is to be certified until May 13 14:09:17 2026 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
root@gabriella:/etc/openvpn/easy-rsa# 

Copy the certificates to their designated place.

root@gabriella:/etc/openvpn/easy-rsa# cp /etc/openvpn/easy-rsa/keys/{server.crt,server.key,ca.crt} /etc/openvpn

Yes we are ready fire up the openvpn server!

root@gabriella:/etc/openvpn/easy-rsa# service openvpn start
root@gabriella:/etc/openvpn/easy-rsa# service openvpn status
● openvpn.service - OpenVPN service
   Loaded: loaded (/lib/systemd/system/openvpn.service; enabled)
   Active: active (exited) since Sun 2016-05-15 17:13:53 EEST; 4s ago
  Process: 2009 ExecStart=/bin/true (code=exited, status=0/SUCCESS)
 Main PID: 2009 (code=exited, status=0/SUCCESS)

May 15 17:13:53 gabriella systemd[1]: Started OpenVPN service

At this point it would be very wise to switch to your ISP's router or firewall setup page and enable port 1194 forwarding between the external IP address of your router and the internal IP address of the OpenVPN server.

The final step will be to generate keys for the client. OpenVPN will not allow two clients with the same key to log on simultaneously, unless you add a line with duplicate-cn in the server.conf parameter file. Client certificates are build the same way as the server's, only this time you get to use the build-key script

root@gabriella:/etc/openvpn/easy-rsa# ./build-key client
Generating a 2048 bit RSA private key
..................+++
................+++
writing new private key to 'client.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) [gr]:
State or Province Name (full name) [Rodope]:
Locality Name (eg, city) [Komotini]:
Organization Name (eg, company) [Aryballos]:
Organizational Unit Name (eg, section) [Aryballos-IT-Services]:
Common Name (eg, your name or your server's hostname) [client]:
Name [server]:
Email Address [admin@aryballos.gr]:

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-1.0.0.cnf
Check that the request matches the signature
Signature ok
The Subject's Distinguished Name is as follows
countryName           :PRINTABLE:'gr'
stateOrProvinceName   :PRINTABLE:'Rodope'
localityName          :PRINTABLE:'Komotini'
organizationName      :PRINTABLE:'Aryballos'
organizationalUnitName:PRINTABLE:'Aryballos-IT-Services'
commonName            :PRINTABLE:'client'
name                  :PRINTABLE:'server'
emailAddress          :IA5STRING:'admin@aryballos.gr'
Certificate is to be certified until May 13 14:31:07 2026 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
root@gabriella:/etc/openvpn/easy-rsa# 

You may create a different key for each of the clients you want to allow access. Otherwise enable the duplicate-cn option on your server configuration file to allow multiple clients to connect with the same key.

Client setup

Each client must have the openvpn package installed. After installation move to the /etc/openvpn folder create a file named client.conf and enter the following:

### Client configuration file for OpenVPN

# Specify that this is a client
client

# Same setting as on server
script-security 3

# Bridge device setting
dev tap
proto udp

# Host name and port for the server (default port is 1194)
# note: replace with the correct values your server set up
remote  extennal_ip.of.openvpn.server 1194

# Client does not need to bind to a specific local port
nobind

user nobody
group nogroup

# Keep trying to resolve the host name of OpenVPN server.
## The windows GUI seems to dislike the following rule. 
##You may need to comment it out.
resolv-retry infinite

# Preserve state across restarts
persist-key
persist-tun
mute-replay-warnings

# SSL/TLS parameters - files created previously
ca /etc/openvpn/ca.crt
cert /etc/openvpn/client.crt
key /etc/openvpn/diaamath/client.key
ns-cert-type server

# Since we specified the tls-auth for server, we need it for the client
# note: 0 = server, 1 = client
tls-auth /etc/openvpn/diaamath/ta.key 1

# Specify same cipher as server
cipher BF-CBC

# Use compression
comp-lzo

# Log verbosity (to help if there are problems)
verb 3

up /etc/openvpn/update-resolv-conf
down /etc/openvpn/update-resolv-conf

Next, copy the files ta.key, ca.crt, client.crt and client.key from the the server to the clients /etc/openvpn. directory.

Disable autostart of the OpenVPN service.

sudo update-rc.d openvpn disable

Reboot the client. (The OpenVPn setup usually fires up the OpenVPN service) And finally connect

sudo openvpn /etc/openvpn.client.conf

That should do it!

Links

This howto has been assembled using various sources. Most important being:

  1. The Ubuntu Community OpenVPN Wiki
  2. The Digital Ocean Tutorail about setting up an Open VPN Server on Debian 9
  3. The OpenVPN howto on the Debian Wiki

No comments :