OpenVPN Server On Raspberry Pi

Overview

Having a great geek out chat with Andrew Gorton and he gave me the idea of setting up an OpenVPN server using a Raspberry Pi. A simple, relatively cheap solution to get access to resources at home.

Pre-Requisites

I will assume that the Raspberry Pi is already setup with power, keyboard or remote access to the terminal running Raspbian without X-Windows (command line online).

If not, have a look at Installing Operating System Images guide.

For outside access, allow port 1194 UDP on your router. You can use TCP by changing the configuration from UDP to TCP but for this I will be using UDP.

Also on the networking side, it’s advised to give your Pi a reservered DHCP address or a static IP because 1. you’ll need to port forward to the Pi and 2. there are steps in the installation that need it’s local IP address.

Install

OpenVPN is a package in apt-get so to install the server:
sudo apt-get install openvpn

Server Configuration

The setup requires priviledged access so to save time switch to the super user until we exit / shutdown / restart:
sudo -s

Copy the example RSA configuration file:
cp -r /usr/share/doc/openvpn/examples/easy-rsa/2.0 /etc/openvpn/easy-rsa

Go to the new directory where the RSA configuration files were copied to:
cd /etc/openvpn/easy-rsa

This is optional but you can increase the strength of the key used to sign everything. Edit /etc/openvpn/easy-rsa/vars and replace:
export KEY_SIZE=1024
to
export KEY_SIZE=2048

Modify the defaults for certificate generation so that there are less typing required. These can be found at the end of the /etc/openvpn/easy-rsa/2.0/vars. For example, to configure a UK (GB) default:
export KEY_COUNTRY=”GB”
export KEY_PROVINCE=”London”
export KEY_CITY=”London”
export KEY_ORG=”amazing.com”
export KEY_EMAIL=”mail@me.com”

If there are 2 export KEY_EMAIL entries then change one and delete the other.

Save and exit the file.

Server Post Install Setup

Everytime you need to make a change to OpenVPN, do the following:
Switch to super user
sudo -s

Go to the base directory where the OpenVPN files are:
cd /etc/openvpn/easy-rsa

Load the helper bash script:
source vars

On first setup or if you want to start from fresh (i.e removing all keys and users created from before) run the following command:
./clean-all

Create a self signed certifcate authority:
./build-ca

Answer the prompts on screen. A tip for UK the correct Country Name is GB not UK. Make sure you can the common name to a domain address or the host name which by default is raspberrypi. Note down these because you’ll have to retype them in the next step. Also the answer you give should not have any spaces.

Create the OpenVPN server key. Replace [Server Name] with a suitable with the common name above:
./build-key-server [Server Name]

The following questions need extra attention:

  1. A challenge password? – Leave it empty
  2. Sign the certificate? [y/n] – Always say yes (y)

Create a key that will help with Denial of Service (DoS) attacks:
openvpn –-genkey –-secret keys/ta.key

Create a new file at /etc/openvpn/server.conf which will contain the server configuration. Copy and paste the contents of this. Here’s an extract:

local 192.168.2.0 # SWAP THIS NUMBER WITH YOUR RASPBERRY PI IP ADDRESS
dev tun
proto udp #Some people prefer to use tcp. Don’t change it if you don’t know.
port 1194
ca /etc/openvpn/easy-rsa/keys/ca.crt
cert /etc/openvpn/easy-rsa/keys/Server.crt # SWAP WITH YOUR CRT NAME
key /etc/openvpn/easy-rsa/keys/Server.key # SWAP WITH YOUR KEY NAME
dh /etc/openvpn/easy-rsa/keys/dh1024.pem # If you changed to 2048, change that here!
server 10.8.0.0 255.255.255.0
# server and remote endpoints
ifconfig 10.8.0.1 10.8.0.2
# Add route to Client routing table for the OpenVPN Server
push “route 10.8.0.1 255.255.255.255”
# Add route to Client routing table for the OpenVPN Subnet
push “route 10.8.0.0 255.255.255.0”
# your local subnet
push “route 192.168.2.0 255.255.255.0” # SWAP THE IP NUMBER WITH YOUR RASPBERRY PI IP ADDRESS
# Set primary domain name server address to the SOHO Router
# If your router does not do DNS, you can use Google DNS 8.8.8.8
push “dhcp-option DNS 192.168.2.1” # This should already match your router address and not need to be changed.
# Override the Client default gateway by using 0.0.0.0/1 and
# 128.0.0.0/1 rather than 0.0.0.0/0. This has the benefit of
# overriding but not wiping out the original default gateway.
push “redirect-gateway def1”
client-to-client
duplicate-cn
keepalive 10 120
tls-auth /etc/openvpn/easy-rsa/keys/ta.key 0
cipher AES-128-CBC
comp-lzo
user nobody
group nogroup
persist-key
persist-tun
status /var/log/openvpn-status.log 20
log /var/log/openvpn.log
verb 1

Modift /etc/sysctl.conf to allow traffic forwarding. Find the line and uncomment it from:
#net.ipv4.ip_forward=1
to
net.ipv4.ip_forward=1

Save and exit the file. Run the following to re-load sysctl.conf:
sysctl -p

Configure the firewall to allow OpenVPN traffic by creating a file in /etc/firewall-openvpn-rules.sh and add the following to it:

#!/bin/sh

iptables -t nat -A POSTROUTING -s 10.8.0.0/24 -o eth0 -j SNAT –to-source 192.168.2.0

Replace the ‘192.168.2.0’s with the Raspberry Pi’s IP address.

Change the file permission and ownser of the firewall config file created above:
chmod 700 /etc/firewall-openvpn-rules.sh
chown root /etc/firewall-openvpn-rules.sh

Edit the network interface file at /etc/network/interfaces and add the new firewall rules. Find the line:
iface eth0 inet dhcp
and add the following. Note the (tab) indentation:
iface eth0 inet dhcp
pre-up /etc/firewall-openvpn-rules.sh

Create the default connection profile to be used by clients at /etc/openvpn/easy-rsa/keys/Default.txt and add the following:

client
dev tun
proto udp
remote [Internet IP or DDNS] 1194
resolv-retry infinite
nobind
persist-key
persist-tun
mute-replay-warnings
ns-cert-type server
key-direction 1
cipher AES-128-CBC
comp-lzo
verb 1
mute 20

Change the protocol from UDP to TCP (if applicable):
proto tcp

Replace [Internet IP or DDNS] with your external (hopefully static) IP address or put the Dynamic DNS address here. For example:
remote danny.no-ip.com 1194
Some of the above can be overriden by the client but it saves a lot of time if the correct defaults are used.

Create a script to generate connection profile files at /etc/openvpn/easy-rsa/keys/MakeOPVN.sh and copy and paste the contents of this. Extract:

#!/bin/bash
# Default Variable Declarations
DEFAULT=”Default.txt”
FILEEXT=”.ovpn”
CRT=”.crt”
KEY=”.3des.key”
CA=”ca.crt”
TA=”ta.key”
#Ask for a Client name
echo “Please enter an existing Client Name:”
read NAME
#1st Verify that client’s Public Key Exists
if [ ! -f $NAME$CRT ]; then
echo “[ERROR]: Client Public Key Certificate not found: $NAME$CRT”
exit
fi
echo “Client’s cert found: $NAME$CR”
#Then, verify that there is a private key for that client
if [ ! -f $NAME$KEY ]; then
echo “[ERROR]: Client 3des Private Key not found: $NAME$KEY”
exit
fi
echo “Client’s Private Key found: $NAME$KEY”

#Confirm the CA public key exists
if [ ! -f $CA ]; then
echo “[ERROR]: CA Public Key not found: $CA”
exit
fi
echo “CA public Key found: $CA”

#Confirm the tls-auth ta key file exists
if [ ! -f $TA ]; then
echo “[ERROR]: tls-auth Key not found: $TA”
exit
fi
echo “tls-auth Private Key found: $TA”
#Ready to make a new .opvn file – Start by populating with the
default file
cat $DEFAULT > $NAME$FILEEXT
#Now, append the CA Public Cert
echo “” >> $NAME$FILEEXT
cat $CA >> $NAME$FILEEXT
echo “
” >> $NAME$FILEEXT

#Next append the client Public Cert
echo “” >> $NAME$FILEEXT
cat $NAME$CRT | sed -ne ‘/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p’ >> $NAME$FILEEXT
echo “
” >> $NAME$FILEEXT
#Then, append the client Private Key
echo “” >> $NAME$FILEEXT
cat $NAME$KEY >> $NAME$FILEEXT
echo “
” >> $NAME$FILEEXT
#Finally, append the TA Private Key
echo “” >> $NAME$FILEEXT
cat $TA >> $NAME$FILEEXT
echo “
” >> $NAME$FILEEXT
echo “Done! $NAME$FILEEXT Successfully Created.”

Change the file permissions of the script:
chmod 700 /etc/openvpn/easy-rsa/keys/MakeOPVN.sh

The next few steps can be done after the client setup to save time but it needs to be done before using OpenVPN.

Create the key exchange:

WARNING: This can a LONG time (for 2048 server key it took over 15 minutes):

./build-dh

The server is now done and it’s time to reboot:
sudo reboot

User Setup

Whilst you can share users between devices, it is best to generate a user account per device so that any compromised accounts do not affect others. Also it’s free to setup as many users as you want. The only hassle is generating and remembering the usernames and passwords (which you should be using a password manager for!).

Switch to super user:
sudo -s

Go to the RSA directory:
cd /etc/openvpn/easy-rsa

Load the helper bash script:
source vars

Create key for new user
./build-key-pass [Username]

  1. Enter PEM pass phrase – This is the password for the account. It will ask for this twice.
  2. A challenge password? – Leave empty.
  3. Sign the certificate? [y/n] – Say (y) yes

Use des3 encryption. This is required for mobile devices and also more secure albeit for a little bit more command foo:

Go to the keys directory
cd keys

Run des3 on the generated user keys:
openssl rsa -in [Username].key -des3 -out [Username].3des.key
Each key is named by the username when creating the user account so replace [Username] with the correct username / file name. It will prompt for the user’s password.

Generate user connection profiles:
./MakeOPVN.sh

Look for the output Done! [username].opvn Successfully Created. for a successful run. It will create .ovpn files for each user usually named after their username.

The next challenge is getting these files off the server due to the restricted nature of the setup. Running the above script creats .ovpn files. These are helper files containing the setup profile needed on your device.

I use WinSCP to get these files off and temporarily changing the folder / file permissions to allow the pi user access:
sudo chmod 705 /etc/openvpn/easy-rsa/keys
sudo chmod 704 /etc/openvpn/easy-rsa/keys/*.ovpn

Copy the files then revert it back:
sudo chmod 700 /etc/openvpn/easy-rsa/keys
sudo chmod 700 /etc/openvpn/easy-rsa/keys/*.ovpn

Summary

It’s not the quickest or easiest thing to setup but following tutorial it worked first time (barring copying and paste errors). I tested the connection out using my phone over over GSM to check it worked. It’s a set and forget for the most part and it just needs to be kept up to date like most things using the apt system in Debian.

How to set up a Raspberry Pi VPN server

Building A Raspberry Pi VPN Part One: How And Why To Build A Server

About Danny

I.T software professional always studying and applying the knowledge gained and one way of doing this is to blog. Danny also has participates in a part time project called Energy@Home [http://code.google.com/p/energyathome/] for monitoring energy usage on a premise. Dedicated to I.T since studying pure Information Technology since the age of 16, Danny Tsang working in the field that he has aimed for since leaving school. View all posts by Danny → This entry was posted in Linux and tagged , , , , , , , , , , . Bookmark the permalink.

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.