Home‎ > ‎Dabbles‎ > ‎RaspberryPi‎ > ‎

Connecting Remotely - Building a VPN Server

posted Dec 6, 2014, 1:56 PM by Joshua ‎(Admin)‎   [ updated Dec 19, 2014, 6:56 PM by Joshua S ]
This post demonstrates how to build a Virtual Private Network (VPN) server.  This will allow remote devices (PCs, Phones, Tablets, etc.) to connect to the RaspberryPi from anywhere on the Internet.  Through this connection, you will be able to use that device as if it were connected locally on your home network.  You may use this so you can access your home printer, other computers or storage devices, or so you can access an unfiltered internet if you are at work or somewhere else that filters your connection.

Note:  An earlier post allowed users to connect using OpenLDAP authentication whereas this tutorial relies entirely upon PKI.  If you would prefer that approach, please use that tutorial.

This is the fifth project in the series and assumes the elements performed in several earlier ones are in place and integrated into the template (see the template projects) in order to work.  Additionally, this project assumes you have a static IP set for the RaspberryPi.  No instructions speak to this, because they will vary based upon your environment and where you perform DHCP.  Generally speaking, this is something you will configure at your router by supplying the MAC address of the Pi.  Additionally, the router will need to be configured to port forward TCP port 1194 to the RaspberryPi.  Note, OpenVPN is often configured to use UDP, but this protocol is also often blocked thus TCP will work much more consistently.

Most of these projects can be performed in any order, but if you follow the order outlined here it will all definitely work.  I've found a number of guides to help me, but many have partial documentation, skip key steps, etc.  The goal is to build out a guide with everything you need to complete each step, but let me know if I miss something or it isn't clear.

For each template and initial setup, I used an 8GB memory card.  With the B+, the image you back up will be the full size of the card whether you expand the file system or not.  For the actual projects, I use a mix of card sizes -- generally 32GB, but I like my templates and initial setup configs to be 8GB to reduce the storage size of my backups.

Supply List:
  • MicroSD Card  A digital memory card, initially designed for media (think a camera) but which will serve as the hard drive for the RaspberryPi.  All tutorials will focus on the 8GB size, but you can easily use this process for a larger format also.  This should be pre-loaded with the template image created in the previous project (template step 01).
  • PuTTY  A free SSH client which is excellent for working at the command line.  I know, I know, no one loves the Command Line any more, but the more you use the RaspberryPi the more you will quickly learn that CommandLine > GUI.
  • RaspberryPi B+  The actual RaspberryPi hardware this will all be built around.
  • Win32 Disk Imager  A Free Open Source Software (FOSS) utility to write of image (.IMG) files to various flash card media (SD, MicroSD, etc.).  Download the software from the website.

  • Write the image you plan to enhance to the SD Card and load it into the RaspberryPi.  In this example, we'll use the template file, created in a previous tutorial.  
  • Using PuTTY (or whatever SSH client you prefer) connect to the IP address of the RaspberryPi.  You should know this from the previous step ( in this example), but if you do not, follow the steps at the beginning of the first lesson which show how to use AngryIP scanner to locate the IP address.
  • Once connected, log onto the Pi using:
    • UserID:  pi 
    • Password:  raspberry

  • Raspbian uses Advanced Package Tool (APT) to manage and install software.  First, we need to update the tool using:
    • sudo apt-get -y update
  • Now let's update the software currently loaded.  There are several ways to do this, but if we issue the dist-upgrade command it will intelligently add software, update packages, and remove unneeded packages.
    • sudo apt-get -y dist-upgrade
  • Finally, let's upgrade the Pi Kernel:
    • sudo rpi-update
  • Let's reboot now that the upgrades are complete:
    • sudo reboot

  • OK, good!  Now that everything is updated, let's install our VPN server.  Use the following commands:
    • sudo apt-get -y install openvpn
      • openvpn  The base package for OpenVPN clients and servers.

  • First, we need to perform these actions as root, so let's use Sudo to switch to the root user.
    • sudo su
  • Now, to set up the key infrastructure we need to use the OpenRSA software included with OpenVPN.  Let's start by copying the sample config file so we can edit to to match our needs.  Unfortunately, the cp command's recursion option does not work correctly in the Pi (at least at the current release), so we're going to do this manually.  Let's start by navigating to the example directory (/usr/share/doc/openvpn/examples/easy-rsa/2.0) and make note of all directories and subdirectories.  In this case, we have the main directory and the tmp directory.
    • cd /usr/share/doc/openvpn/examples/easy-rsa/2.0
    • ls -al
    • cp /tmp
    • ls -al

  • With the directory structure understood, let's move to our destination directory and create the receiving directories.
    • cd /etc/openvpn
    • mkdir easy-rsa
    • cd easy-rsa
    • mkdir tmp
  • With the folders created, let's copy some files!
    • cp /usr/share/doc/openvpn/examples/easy-rsa/2.0/* /etc/openvpn/easy-rsa
    • cp /usr/share/doc/openvpn/examples/easy-rsa/2.0/tmp/* /etc/openvpn/easy-rsa/tmp
  • Note, we are currently in the /etc/openvpn/easy-rsa directory.  Let's open and edit the vars file, using nano, so when we start creating certificates the default values match what we want.  Note, the second variable KEY_SIZE -- this tutorial recommends increasing this to 2048 to enhance security, but it can be left at 1024 for slightly better performance.  Edit the following lines to match the following values.  A full example of this file is attached at the bottom of this lesson for reference.
    • export EASY_RSA=”/etc/openvpn/easy-rsa”
    • export KEY_SIZE=2048
    • export KEY_COUNTRY="<choose a two ISO Country code>"
    • export KEY_PROVINCE="<choose a state or province name>"
    • export KEY_CITY="<choose a city name>"
    • export KEY_ORG="<choose a company or organization name>"
    • export KEY_EMAIL="<choose a contact eMail address>"

  • Good job, the basics are set up, and now it's time to build out our Certificate Authority (CA) infrastructure.  First, we need to build the root certificate and the root key.  Note values in the "[]" fields should match what was input in the vars file.  If you simply strike "enter", you will accept these values.  For this step, any values you enter will work.  Use these commands
    • source vars
    • ./clean-all
    • ./build-ca
  • Now, we need to build the OpenVPN server keys using the following command:
    • ./build-key-server <VPN Server Name>

  • With the server built, let's add a couple certificates for our clients "WGBW7001" and "WGBW7002".  Below is the process used for "WGBW7001", but the process is identical for each client except for the input name.  Note, the PEM Passphrase will be used to log onto the VPN, so the user must remember this password.
    • ./build-key-pass <client name>

  • Unfortunately, mobile platforms do not work well with the default keys we've generated, thus we need to generate special 3DES keys for any clients running a mobile platform.  Do this with the following commands:
    • cd keys
    • openssl rsa -in <client name>.key -des3 -out <client name>.key.3des.key
  • Good.  We have our CA created, the certificates generated for our VPN Server and VPN Clients.  Now, we need to generate our Diffie-Hellman parameters which allow us to exchange the key securely when the connection is established.  Note, this takes a very long time -- especially on a RaspberryPi.  Use the following commands:
    • cd /etc/openvpn/easy-rsa/
    • ./build-dh
  • We're almost complete.  With the Diffie-Hellman parameters generated, we need to create the OpenVPN-HMAC Key using the following command:
    • openvpn –-genkey –-secret keys/ta.key
  • The core server elements are complete.  We now need to create the server config file (/etc/openvpn/server.conf) in order for it to know how to operate.  A sample file has been attached for reference.  Make sure to update the following fields:
    • local <the Pi's IP Address>
    • proto tcp
    • port 1194
    • cert /etc/openvpn/easy-rsa/keys/<VPN Server Name>.crt - AD-VPN-Server.crt
    • key /etc/openvpn/easy-rsa/keys/<VPN Server Name>.key
    • dh /etc/openvpn/easy-rsa/keys/dh2048.pem
    • push "route <local subnet IP base>" 
    • push "dhcp-option DNS <DNS Server IP Address>" 
    • cipher AES-256-CBC

  • Open and edit the /etc/sysctl.conf file using nano.  Update the following line:
    • net.ipv4.ip_forward=1

  • Apply the changes using this command:
    • sysctl -p
  • Now we need to create a script (/etc/firewall-openvpn-rules.sh) which will modify our firewall rules to allow OpenVPN to function on this server.  A sample script is attached at the end of this tutorial.  Update the following line:
    • iptables -t nat -A POSTROUTING -s -o eth0 -j SNAT --tosource <VPN Server Address>

  • Now, this file will be executed by root, thus we need to change the file permissions and ownership using the following commands:
    • chmod 700 /etc/firewall-openvpn-rules.sh
    • chown root /etc/firewall-openvpn-rules.sh
  • Now we need to edit the network interface file (/etc/network/interfaces) using nano.  A sample file is attached at the end of this tutorial.  Insert the following line beneath the iface for eth0:
    • pre-up /etc/firewall-openvpn-rules.sh
  • Great job!  The server configuration is complete.  Go ahead and reboot the server using the following command:
    • reboot
  • Good news!  We're down to the final piece of the tutorial -- building the .ovpn files you will need for each client you built keys for.  These can be manually configured, but why do something manually (and risk user error) when we can build a script to do it for us.  We are going to build a script that reads in each important file to build the .ovpn file -- for any clients with both a normal .key and a .key.3des.key file, it will generate .ovpn files for both.  Let's start by building out the file with all of our default values at /etc/openvpn/easy-rsa/keys/Defaults.txt.  An example file has been attached to the bottom of this tutorial for reference.  Key fields to make sure you update include:
    • proto tcp
    • remote <external IP or URL> 1194
    • cipher AES-256-CBC
  • OK, now that our default file is ready, let's build our script.  Upload the attached script at the end of this tutorial to /etc/openvpn/easy-rsa/keys/MakeOVPN.sh then update the owner and permissions using the following commands:
    • chmod 700 MakeOVPN.sh
  • OK, now we just need to execute our script and follow the prompts by entering each client name.  Use this command for each:
    • ./MakeOVPN.sh
  • Securely transfer the .ovpn files to each client.  This may be done with a form of SFTP or through a cloud service, but consider using encryption along the way to ensure the file is protected.  Remember, this is half (the other half being the password) of what is needed to remotely access your network.  The actual configuration will vary somewhat from client to client based on how OpenVPN is deployed in that environment.
  • Securely transfer the following files from the RaspberryPi, purge them from the Pi, and store them securely offline.  Note -- do not remove the server, CA, TA, dh2048, etc. files.
    • <Client>.key
    • <Client>.key.3des.key
    • <Client>.ovpn
    • <Client>.ovpn.3des.ovpn
  • Power off the RaspberryPi and pull out the MicroSD card.  Insert it into your computer's card reader and run Win32 Disk Imager.  Create a new image file you name as your backup for the VPN Server image and select the "Read" button.  
  • Congratulations!  Your VPN is now ready to go!  
Joshua (Admin),
Dec 7, 2014, 5:44 AM
Joshua (Admin),
Dec 7, 2014, 5:56 AM
Joshua S,
Dec 7, 2014, 11:44 AM
Joshua S,
Dec 7, 2014, 11:58 AM
Joshua (Admin),
Dec 7, 2014, 4:12 AM
Joshua (Admin),
Dec 7, 2014, 5:27 AM