EricDoerr.com

Setting up Raspberry Pi as an OpenVPN router

A guide to setting up a linux box as a VPN router for your network

Home - Last Updated: 02.24.14

This guide is designed specifically to use ProXPN's OpenVPN servers on the Raspberry Pi as a VPN router using Raspbian as the Pi's operating system. Any VPN solution with accessible config files and any Debian-based linux distribution should work using this guide, but may require modifications to the code. This setup will also allow an AppleTV (or any device without a built in VPN client) to work behind an encrypted tunnel by simply changing the Router IP to the IP of your new VPN Router.

Preface

I used HideMyAss as my VPN solution for six months. They were great- 569 servers worldwide, full L2TP/PPTP/OpenVPN encryption, and I personally experienced consistent speeds over 20 Mbps in the US tunneling to the Bay Area and then to my location in Reno. After my half-year subscription expired as a satisfied customer I decided to roll the dice (via Bitcoins) and switch over to ProXPN after years of their sponsorship of the now defunct NSFW Show (born again, here) on the TWiT Network. We'll see how service over the next few months goes, but after some research and programming I now have a simple working VPN router with ProXPN. Not only can I secure my connection on the go, but I can now say goodbye to ridiculous geographical content restrictions (*cough* MLB.TV blackouts) on my AppleTV by routing the connection through my Pi.

Requirements

I'm using the old 256MB version of the Model B, which still works fine for this. I'm also using the Transcend 8GB Class 10 SDHC (though 8GB is not required I still recommend a Class 10 SDHC for the speeds). The HDMI/Monitor/Keyboard/Mouse are all temporary for initial setup. After that, we'll be using an SSH connection (explained later).

Feel free to skip ahead to the OpenVPN setup if you already have a blank SD card or an updated version of Raspbian.

(Optional) Backing up SD card (OSX)

This step is for anyone who currently has a running setup on their SD card that they want to save. The following commands are to be typed in the Applications > Terminal of OSX. If you're on Linux or Windows, check here and here respectively for backing up your SD card.

diskutil list
diskutil unmountDisk /dev/diskX
sudo dd if=/dev/rdiskX bs=1m | gzip > ~/Desktop/pi.gz

The first line lists the connected disks. The second line unmounts your SD card (where X is disk number of your SD card as shown in the previous line command). The third line copies the SD card contents (where X is the disk number) with a 1MB block size, and then compresses the backup into a gzip file on to the desktop. Be sure your X in rdiskX is the correct number or you will be backing up the wrong drive.

For me disklist util lists my disk as /dev/disk2, therefore I replace X with the number 2 in both commands. After executing the third command, a blinking cursor will appear for the next couple of minutes until completion. If you're uncertain it's working, check the info of the newly created pi.gz on the desktop and see if the size is growing.

Formatting and installing Raspbian

Directions for formatting and copying the install image of Raspbian to your SD card can be found here. Ignore the parts of the guide that suggest using NOOBS; instead skip to sections 3.1, 3.2, or 3.3 depending on your desktop operating system (as we know we only want to use Raspbian as our Pi OS). Follow the directions carefully as you can easily format the wrong drive if you don't double check disk numbers. Duh, I know, but really- use extreme caution when dealing with anything that can erase data.

Direct link of latest Raspbian can be found here and latest torrent is here. As of this guide I am using 2014-01-07-wheezy-raspbian.zip.

Initial Raspbian Setup

Once Raspbian's image has been copied to the SD card, connect everything together and boot your Pi. You should be greeted by the blue raspi-config screen after everything has loaded.

First step is to go Internationalisation Options to change your locale, timezone, and keyboard layout. Using spacebar to enable/disable options and enter to accept changes, these are my settings for West Coast USA:

Obviously your settings will differ if you aren't in the Pacific timezone in America, but getting your settings accurate for your setup is important or else your time will be off and your keys may result in different outputs. Note that I kept en_GB.UTF-8 selected as a locale as a backup option, but changed it from default.

After setting your location settings, chose option 1 Expand Filesystem. This will resize the partition to fill the remainder of the SD card. Next is option 2 Change User Password. By default, the username is pi and password is raspberry, but you should always change the password from the default.

Everything else is optional, but here are my personal changes:

I use the modest overclocking setting because it gives the processor a little more core clock without increasing voltage. The hostname doesn't be changed, but the option is there if you don't want raspberrypi. I dropped the GPU memory to 16 since this is a command-line setup.

When you're satisfied with your settings, arrow down to select Finish and Yes to reboot. You now have a working Raspbian command-line OS! After reboot you should be greeted with the login prompt. Use pi as the username, with your password set above as the password. Congrats, you're in! Now we need to set a Static IP address for the Pi and update packages.

Changing from DHCP to Static IP

We need to edit the current interfaces so the ethernet port uses a static IP address instead of a DHCP. Using nano as our editor, open the interfaces file:

sudo nano /etc/network/interfaces

Now arrow down to change dhcp in line 4 to static so it appears as the following:

iface eth0 inet static

After changing dhcp to static, we need to add in a few more lines to assign the static addresses. The address variable is used to assign the Pi's IP address. Here is my final interfaces file with the changes in bold:

auto lo

iface lo inet loopback
iface eth0 inet static
address 192.168.0.135
netmask 255.255.255.0
network 192.168.0.0
broadcast 192.168.0.255
gateway 192.168.0.1


allow-hotplug wlan0
iface wlan0 inet manual
wpa-roam /etc/wpa_supplicant/wpa_supplicant.conf
iface default inet dhcp

Your values will differ from mine if your router is on a different subnet than /24 and has a different IP than 192.168.0.1. For a more detailed explanation on these values and the modification of the interface file, check out ModMyPi's static IP tutorial.

Once you've added in your addresses, hit Ctrl+X to exit, Y to confirm, and Enter to save changes. This calls for another reboot:

sudo reboot

After the Pi reboots, you should see the updated IP address printed before the login prompt. To test your new connection, log in and run a traceroute to Google:

traceroute google.com

If you edited the interfaces file correctly you should be seeing the hops between servers as your connection loads google.com. Now that the network IPs are settled it's time to get Raspbian up to date:

sudo apt-get update
sudo apt-get upgrade

You should have some core packages that need updating. Press Y to download and install the updates. You're moving right along.

(Optional) Use SSH to connect to Pi

If you're on a UNIX based operating system (OSX, linux) you can use the built-in Terminal to access your Pi from your current system. Windows requires a program like PuTTY to do this. To connect to the Pi from Terminal, type the following:

ssh username@ipaddress

In the above code I use pi as username before @ and 192.168.0.135 in place of ipaddress as that is the IP address I assigned it when we assigned a static IP to the Pi. You will be asked to add the RSA key fingerprint, to which you need to reply with yes to add the key to your list of known hosts. The password prompt will follow and ask you to enter the password you specified in the initial setup phase. You should now see the same prompt that displays after logging in directly from your Pi. If you successfully connect via SSH, you can unplug your monitor/keyboard/mouse and continue using the SSH connection.

Allow IPv4 Forwarding

Now we're getting into the core of the guide. At this point you will need to have a working and updated Raspbian installation with a static IP address.

For this we need to edit a system config file:

sudo nano /etc/sysctl.conf

Scroll down and delete the hash # preceding the line net.ipv4.ip_forward=1 so it looks as follows:

net.ipv4.ip_forward=1

Save and exit using Ctrl+X, Y, ENTER.

Setting up iptables

This step allows the Pi to be used as a router by using iptables which is built into Raspbian. Matthew Manning has compiled a script to make this process much easier for us. To download and setup his script, execute the following commands:

sudo -s
wget http://mwmanning.com/share/iptables.test.rules
cp iptables.test.rules /etc/iptables.test.rules
iptables-restore < /etc/iptables.test.rules
iptables-save > /etc/iptables.up.rules

Note that I went into superuser mode in the first line. I needed to do this save the new file into the permanent one. More on the above commands can be found on here.

Now we need to load the rules on boot:

nano /etc/network/if-pre-up.d/iptables

This will create a new file. Paste the following into the new file, save & exit:

#!/bin/bash
/sbin/iptables-restore < /etc/iptables.up.rules

Now make the iptables files executable:

sudo chmod +x /etc/network/if-pre-up.d/iptables

Boom. Now reboot and you should have a working router!

sudo reboot

To test that your Pi is working as a pass-though router, update your IP settings by changing the Router IP to your Pi's IP address. For me, this means changing 192.168.0.1 to 192.168.0.135. Your addresses may differ, but these are the same addresses we used when setting up the Pi with a Static IP earlier. Open a browser and test your connection.

Installing OpenVPN

We're going to install OpenVPN and screen using the following commands:

sudo apt-get install openvpn screen

Installing OpenVPN profiles

The following steps will differ depending on which VPN provider you are using, but the process should be relatively the same. You need to find your VPN providers config files to install into the client. These should be easily locatable on the providers website, but the ProXPN took some deep searching on behalf of others. From this point forward, I will be centering directions around my ProXPN setup.

Below is the commands I used to download and unpack ProXPN's config files that are contained in the source of their OSX client:

wget https://www.proxpn.com/proxpn_mac_source.tar.gz
sudo tar -zxvf pro*
sudo mkdir ProXPN
sudo cp -r ~/MacOSX/config/* ~/ProXPN
sudo rm -rf ~/MacOSX
sudo rm proxpn_*
cd ~/ProXPN

For ProXPN users the above commands downloads the OSX source in the home folder, gzip's the archive, creates a folder in the home directory called ProXPN, copies the proxpn.ovpn profile and keys to the newly created ProXPN folder, deletes the archive and its folders, and moves you into the ProXPN folder.

(Optional) Auto-authenticate VPN credentials

Rather than type my login credentials every connect, I created a file to store my password that OpenVPN will use to authenticate me. Note that this does keep your credentials in a text file, but if you are okay with this type the following:

cd ~/ProXPN
sudo nano password.txt

Type in your username in the first line and your password on the second line. Save and exit. Now we need to modify our config profile to read the password.txt automatically:

sudo nano ~/ProXPN/proxpn.ovpn

Scroll down to the auth-user-pass line and change it to the following:

auth-user-pass password.txt

Now when you connect in the next step it should auto-authenticate.

Testing our OpenVPN connection

Now we will be connecting to our VPN servers. In this example I will be connecting to ProXPN's Los Angeles server. Make sure you are in ~/ProXPN or whatever folder you are using for the config files:

sudo openvpn --config proxpn.ovpn --remote la1.proxpn.com 443

The VPN should be connecting using the proxpn.ovpn config file. There will be lines of scrolling text and it will stop and ask for your VPN authentication. You can change this later to allow the script to auto-authenticate you, but now enter your credentials. If all goes well, the last line you should see should be the date/time followed by:

Initialization Sequence Completed

w00t! You're connected! If you still have your Router IP set to the IP of the Pi, confirm your IP and location are different.

To close the VPN connection, hit Ctrl+C. This will revert the Pi back to a normal router and return your to the command prompt. Check your IP and location again and confirm they are your normal connection.

You now have a working VPN router. However, we'd like to simplify the process without requiring a long command.

Simplifying connection commands with .bash_aliases

Linux has a file hidden in our user directories that can use a single word to replace an entire command. Rather than using the whole command above, I modified my .bash_aliases file to connect to Los Angeles by simply typing in la.

To edit the .bash_aliases file, type in:

sudo nano ~/.bash_aliases

This file should be empty unless you aren't using a new Raspbian install. Paste the following, save & close:

alias uk='cd ~/ProXPN && screen sudo openvpn --config proxpn.ovpn --remote uk1.proxpn.com 443 && cd ~/'
alias sea='cd ~/ProXPN && screen sudo openvpn --config proxpn.ovpn --remote se1.proxpn.com 443 && cd ~/'
alias sing='cd ~/ProXPN && screen sudo openvpn --config proxpn.ovpn --remote sg1.proxpn.com 443 && cd ~/'
alias nyc='cd ~/ProXPN && screen sudo openvpn --config proxpn.ovpn --remote ny1.proxpn.com 443 && cd ~/'
alias bkn='cd ~/ProXPN && screen sudo openvpn --config proxpn.ovpn --remote bny1.proxpn.com 443 && cd ~/'
alias nl='cd ~/ProXPN && screen sudo openvpn --config proxpn.ovpn --remote nl1.proxpn.com 443 && cd ~/'
alias mia='cd ~/ProXPN && screen sudo openvpn --config proxpn.ovpn --remote mfl1.proxpn.com 443 && cd ~/'
alias la='cd ~/ProXPN && screen sudo openvpn --config proxpn.ovpn --remote la1.proxpn.com 443 && cd ~/'
alias dal='cd ~/ProXPN && screen sudo openvpn --config proxpn.ovpn --remote d1.proxpn.com 443 && cd ~/'
alias cz='cd ~/ProXPN && screen sudo openvpn --config proxpn.ovpn --remote cz1.proxpn.com 443 && cd ~/'
alias attach='screen -r'

These changes won't be applied until you reboot, but now you can type in uk to connect to the London server, sea to connect to Seattle, and so on. Reboot and try out all the commands.

For reference, uk=United Kingdom, sea=Seattle, sing=Singapore, nyc=New York City, bkn=Brooklyn, nl=Netherlands, mia=Miami, la=Los Angeles, dal=Dallas, cz=Czech Republic

When we previously tested our connection to LA earlier, we had to press Ctrl+C to kill the connection. While that is still how we kill the connection, we can now hit Ctrl+A+D to hide the connection into the background using the installed screen utility. This allows us to continuing using the command prompt while still being connected. To get back to the connection screen from the command prompt, type screen -r or attach as you see as the last alias. Now you can hit Ctrl+C to kill the connection as we did before and return to the command prompt with the Pi acting as a pass-through router.

If you haven't tried already, go into the IP settings of your AppleTV or whichever device you want to use through the VPN client and test it out both in pass-through mode and also in VPN mode. You should be good to go!

References

Questions? Comments? Support?
Contact me via Twitter: @0x01_

BTC: 1DLSjrkm63tW5t244GQEfp3zJW1e5qKLi6
LTC: LQVuJB13SXf2TeYaawQ11zLD9r2m98yhLH
DOGE: DC3Gu4sLQMEo1Pei6tMZtq3tmnXi5j7g2G

Home