A new version of this series has been published. Please refer to the new index for updated articles and ordering. This article is kept for historical reference, but should be considered out of date.
Note: This article is part of a series. See the Index for more information.
Self-promotion: I’ve recorded this series as a screencast for Pluralsight:
If you have a Pluralsight subscription, please consider watching it. Thanks!
Updates: EasyRSA is no longer installed as part of openvpn, but you can install it through apt-get just like anything else. Just add “easy-rsa” to the list of things to install early on. It will end up in a different place as well, so the command to copy the scripts is now “sudo cp -r /usr/share/easy-rsa /etc/openvpn/easy-rsa”
The export variables at the bottom of vars have moved around a little, there’s now only one copy of your email address, and CN is commented out at the very bottom by default. Just fill in the variables that are present, and leave CN commented out.
Now that the whole house is humming along, sharing files, downloading things, and backing everyone up, you might be wondering if there’s anything left that the Raspberry can do for you. The answer is yes. In this article, we’ll set up the Raspberry Pi to act as an OpenVPN server, allowing you to access your home network from anywhere. OpenVPN is an open-source, cross-platform, virtual private networking (VPN) application. VPNs let you route internet traffic through a secure, encrypted channel, back to a network that you trust and/or control. You may have used one in order to securely access resources on the network at your office when you’re on the road. Developers sometimes use them to simulate traffic coming into their network from outside for testing. You can add these same abilities to your home network so that you can get to your stuff from work, or a hotel, or anywhere else with internet access. Running your own VPN means that no matter where you get an internet connection from, you are effectively “at home”. You don’t need to worry about fellow patrons at the coffee shop listening in on your network traffic because the traffic between you and your VPN is highly encrypted.
Once again, I didn’t invent this stuff. Most of the information about how to set up OpenVPN comes from a whitepaper by Eric Jodoin of the SANS institute. That whitepaper was later paraphrased and simplified in a pair of posts by Lauren Orsini. Both are excellent reading, and go into far more depth about how all this stuff works than I plan to. I’m just putting it into the same format as the other posts in the series, and organizing them in a logical progression, building on top of the previous posts in this series.
In order to connect to your home network’s VPN when you are away from home, you are going to need either a static IP address, or a dynamic IP resolution service like www.no-ip.org. My home router updates no-ip automatically, so I have not set up a program on the Raspberry Pi to do this. Other tutorials exist out there to handle this part.
Warning: The explanation that follows is super-non-technical™, and probably wildly inaccurate in many important ways. I am not a security or cryptography expert, but this is, in layman’s terms, how internet security works. When you visit your bank’s website, and something in your address bar turns green, or grown a little lock, it means that someone at the bank went to some authority that we’ve all agreed to trust, and got a certificate that says “Yup these guys are the bank alright”, and installed it on the web server you’re talking to. As long as you trust the people that made the certificate to only give it to the company that paid for it, and as long as you trust the bank to only install the certificate on their own servers, then you have a way to prove that the server you’re talking to belongs to the company you think it does, or at least a company that the authority vouched for. Although I’m sure you trust your own word that the Raspberry Pi Home Server that you’ve been building is your own, your other computers are still going to want proof that the thing on the other side of the internet is your server, and not someone else pretending to be your server. That’s kind of the whole point of this exercise, after all. Since you trust yourself, you can act as your own “certificate authority” and make your own certificates. You then install your homemade certificates on both the server and the client, and they use that certificate to encrypt traffic back and forth between them.
First things first, you’ll need to install the OpenVPN software onto the Raspberry Pi. You’ll also need the OpenSSL package in order to secure your connection later on. Installing both is as simple as…
sudo apt-get install openvpn openssl
That’s the easy part. Now comes the configuration. The installer has created some sample configuration files for us, and they’ll form the skeleton of the configuration. Copy the entire directory of sample configuration files like this:
sudo cp -r /usr/share/doc/openvpn/examples/easy-rsa/2.0 /etc/openvpn/easy-rsa
Open the vars file for editing.
sudo nano /etc/openvpn/easy-rsa/vars
Find the “EASY_RSA” entry, set it as follows:
Move to the bottom of the file, and change the defaults that are defined there to match your location and network. This will save you some time later on when you are asked to provide this information again for each user you set up. Mine looks like this:
export KEY_COUNTRY="US" export KEY_PROVINCE="OH" export KEY_CITY="Columbus" export KEY_ORG="Home" export KEY_EMAIL=melgrubb@…
Explaining the next few settings is a little out of my depth, but I’ll try to explain to the best of my understanding.
export KEY_CN=RPHS export KEY_NAME=RPHS export KEY_OU=RPHS export PKCS11_MODULE_PATH=RPHS export PKCS11_PIN=1234
Most of these can be anything you want, but the KEY_CN setting must be unique, so if you’re going to make more than one VPN server, give them different values. I’ve chosen to make my “Common Name” (CN) the same as the name of the server. KEY_NAME will affect the name of the resulting key file, but is otherwise arbitrary. The organization unit (OU) setting is not important for a small home network, so I’ve just gone ahead and used the server name again. Basically, you can just make all of these values the same thing, and you’ll be just fine. The last two settings have to do with smart cards, which we’re not even going to get into. Close Nano, saving the file (ctrl-x, y, enter)
Become a certificate authority
In order to create certificates, you’ll need… wait for it… a certificate. In this case, it’s a “root certificate”. This is the kind of thing that one of the trusted authorities out on the web would have. The “easy-rsa” package you installed earlier can generate such a certificate for you. Run the following commands to set up a key server. Notice that the “sudo su” command is being used here. You’re going to stay in “god mode” for pretty much the remainder of this post.
cd /etc/openvpn/easy-rsa sudo su source ./vars ./clean-all ./build-ca
Note: Newer installations will say “Generating a 2048 bit RSA private key”. This default has changed since I originally published this article. Pay attention to what your installation says because you’ll need to know this in a minute. Also, 2048-bit keys take a LOT longer to generate, so your screen is going to look quite different than this screenshot.
When that finished, enter the following command, accepting the defaults again. You’ll get a couple extra questions this time. Make sure the “challenge password” is blank, and accept any other defaults.
You may be able to just take your bank’s word for it that they are who they say they are, but VPN servers like, the one we’re building, want proof of the client’s identity as well. They won’t let just anyone in. You need to give a key to each device or user you want to allow to connect to the VPN server. You have a decision to make at this point. You could generate a unique key for each individual device that you want to connect via VPN, or you could take a shortcut and generate a key for each user. The difference is whether you expect to need to connect more than one device at the same time. If you don’t need to connect more than one device per user at the same time, generate a key named for the user. If you think users will need more than one device connected at the same time, I’d suggest naming the key after the device. Whichever you decide, generate a key like this:
Accept the defaults again, leaving the challenge password blank. The PEM password, is the password you’ll need to connect using the key. Pick something nice and strong, but also something you won’t forget. If you want to be really paranoid, you could randomly generate one and keep it in a password safe. The choice is yours. Leave the challenge password blank again. Sign and commit the certificate when prompted. Almost done.
cd keys openssl rsa -in NAME.key -des3 -out NAME.3des.key
Use the same password as you did before. You’ll have to enter it three times. Technically, the first time is a different password, but how are you supposed to keep them straight?
cd .. ./build-dh
You may need to wait a while for this last step. Sometimes you get lucky, and this step is short. sometimes you’re unlucky, and it takes a long time. You never know what kind of wait you’re in for up front. When it’s done, generate a hash-based message authentication code (HMAC). This is yet another layer of protection, and helps to prevent denial of service (DOS) attacks.
openvpn --genkey --secret keys/ta.key
Configure OpenVPN Server
Now it’s finally time to edit the OpenVPN configuration and tie up the loose ends.
You’ll notice that the editor is totally blank. That’s because this file doesn’t exist yet. Paste in the following text, substituting your own values for the highlighted values. You’ll need your Raspberry Pi’s IP address, the IP address of your router, and the name you used above when calling build-key-server.
Note: I have also highlighted the 8th line, where it says “dh2048.pem”. Older installations defaulted to a 1024-bit key, so you will need to adjust this if you’re working with an older installation. If you’re installing it for the first time, however, this should say 2048 these days. Just make it match what the build-ca step said above.
local 192.168.1.XXX # YOUR PI'S IP ADDRESS dev tun proto udp port 1194 ca /etc/openvpn/easy-rsa/keys/ca.crt cert /etc/openvpn/easy-rsa/keys/RPHS.crt key /etc/openvpn/easy-rsa/keys/RPHS.key dh /etc/openvpn/easy-rsa/keys/dh2048.pem.pem 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.1.0 255.255.255.0" # YOUR PI'S IP SUBNET # Set primary domain name server address to the SOHO Router # If your router does not do DNS, you can use Google DNS 18.104.22.168 push "dhcp-option DNS 192.168.1.1" # YOUR ROUTER'S IP ADDRESS # Override the Client default gateway by using 0.0.0.0/1 and # 22.214.171.124/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
Exit nano, saving your changes (ctrl-x, y, enter) Next, you need to allow the Raspberry Pi to forward IP traffic, which it does not do by default.
Find the line that says “Uncomment the next line to enable packet forwarding for IPv4”, and uncomment the line immediately after it.
# Uncomment the next line to enable packet forwarding for IPv4 net.ipv4.ip_forward=1
Exit Nano, saving your changes (ctrl-x,y,enter), and force a reload of the settings.
The Raspberry Pi has its own firewall, which must be configured to allow the VPN traffic through. Create a script file to automate the opening of the appropriate ports.
Copy in the following text, substituting your own Raspberry PI’s IP address where highlighted.
#!/bin/sh iptables -t nat -A POSTROUTING -s 10.8.0.0/24 -o eth0 -j SNAT --to-source 192.168.1.XXX
Change the permissions on the file you just created so that it can be executed, and assign ownership to the root user.
chmod 700 /etc/firewall-openvpn-rules.sh chown root /etc/firewall-openvpn-rules.sh
This script file needs to run every time the Raspberry Pi boots up in order to do us any good. Edit the /etc/network/interfaces file.
Find the line that configures the wired ethernet port. If you are running your server wirelessly, then you’ll need to adjust accordingly. Insert a new line, indented underneath so that the result looks like this:
... iface eth0 inet dhcp pre-up /etc/firewall-openvpn-rules.sh ...
This will ensure that the firewall rules are applied to that network interface even before it has started up. Reboot the Raspberry Pi so that the rules are applied.
Generating client keys
Connecting a VPN client to a remote server takes a bit of configuration, too. The OpenVPN client has to know where the server is, and it has to have a copy of the keys we generated earlier. All of this configuration gets wrapped up into a file with a .ovpn extension. You can create these by hand if you like, but Eric Jodoin, the author of the original SANS.org article was kind enough to write a script to do it for us. Create the script file.
This is a new file, so it will be totally blank. Paste in the following:
#!/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."
Exit Nano, saving your changes (ctrl-x,y,enter) Once again, because this is a script, permissions will have to be altered to allow it to run.
chmod 700 /etc/openvpn/easy-rsa/keys/MakeOVPN.sh
Create the Default.txt file to hold the default values the script will use. The casing isn’t important, but it must match what was specified at the top of the script file. I’m keeping the capitalized “D” just to keep it the same as anyone else who followed Eric’s instructions.
Paste in the following, substituting your public IP address for the highlighted text. If you don’t have a static public IP address, you can use a dynamic name from a service like DynDNS or no-ip here as well. The “1194” is the standard port number OpenVPN uses, adjust as needed to match your network configuration.
client dev tun proto udp remote YOUR_PUBLIC_IP_ADDRESS 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
Exit Nano, saving your changes (ctrl-x,y,enter) Execute the script to create a .ovpn file. Remember to use the user or device name you chose earlier when creating the client key. cd /etc/openvpn/easy-rsa/keys ./MakeOVPN.sh The result is a NAME.ovpn file in the /etc/openvpn/easy-rsa/keys folder on the Raspberry Pi. That’s great, but we need the key on the client machine. You can copy the file using a secure copy program like WinSCP, copy it to a flash drive and move it by hand, or any other number of ways to move a file around. Since this is my own private home server, I’m going to put the file on the data share, at least temporarily. Once the key is installed and working on the client, I’ll delete it from the server.
cp /etc/openvpn/easy-rsa/keys/NAME.ovpn /mnt/data/
Keys like this aren’t something you should leave lying around. On the other hand, you should probably have a backup of them somewhere. If you put them on a flash drive, go put it in a safe or something. Don’t let anyone get a hold of your keys, or they have a free pass into your home network, and you may not even notice it. You can always go back and generate new keys, delete the compromised ones, and continue on, of course.
Before you’ll be able to connect to your home network from outside, you’ll need to set up your router to forward all traffic on port 1194 to the Raspberry Pi. I can’t tell you how to configure the firewall on your router at home because I don’t know what kind of router you have. An excellent resource that may have information specifically for your router is http://portforward.com/.
I’m using the OpenVPN client for Windows, but the instructions should be similar for other platforms. You can download open-source clients for Windows, and source tarballs for other systems from here. Note: Don’t try to download client software from the links on the front page of the OpenVPN site or you’ll just end up with “SecureTunnel”, a paid-subscription-based system that lets you do exactly what you’re already set up to do on your own. Get the .ovpn file that you generated on the Raspberry Pi over to the computer you’re going to connect from, and put it in the OpenVPN config folder. For Windows users, this should be C:\Program Files\OpenVPN\config.
Connecting the client
You’ll need to be somewhere other than on your own network for this next part. Otherwise you’re seriously crossing the streams, shutting down the containment grid, etc. Disconnect from your home network and tether yourself to a phone or something before continuing. Run the OpenVPN GUI application. It should have created a shortcut in your start menu for Windows 7 users, or on your app list for Windows 8 users. Run it, and it should pick up on the .ovpn file and open a connection. You’ll be prompted for the password you created earlier, and if everything is configured correctly, the OpenVPN icon in your notification area should turn green, and you’ll be effectively connecting to the outside world as part of your home network. There are, of course, many issues you could run into when using a VPN. Most of them are explained pretty well on the HowTo page of the OpenVPN site. One of the more vexing problems is that of disambiguating IP addresses between your home network, and the network you are connected to. See “Numbering Private Subnets” for more information.
With this article complete, you’ve built a home server that’s covering all of the essentials. From here on out, we’ll be adding bells, whistles, fringe on top, etc. In the next post, we’ll add the LAMP stack, which forms the basis for most Linux-based web projects. If you want to run a website, a blog, or just a few web applications, you’ll probably need this.