My girlfriend, who has a very sweet tooth got quite upset about this. I kept mentioning this raspberry pie I'd ordered and she was getting kind of excited about the prospect of it being delivered. She couldn't quite fathom why I'd ordered a pie from eBay instead of just getting one from the supermarket, but chose not to question me about it. When I told her it had finally arrived, her face lit up. That is until I dangled the small circuit board in front of her. She just gave me a look that was equal parts confusion and disappointment.
Before I go any further with the lab build I decided to configure the Raspberry Pi I bought. Initially the device was meant to provide a way of issuing Wake-On-LAN commands to my ESXi hosts remotely, but after tinkering with the Pi for a bit and doing a spot of Googling it seemed it had the potential to perform a number of other functions for me too.
The best £30 I've ever spent; is how I've often described the Raspberry Pi to people who ask about it. In reality it was more like £60 once you factor in the accessory bundle, but still for what it's given me, I think it's a bargain. I initially bought the Pi because I wanted a low power device I could leave on all the time from which I could issue Wake-On-LAN packets to my ESXi hosts. As a consultant, I sometimes spend a lot of my time living out of hotels Monday to Friday. I envisaged a scenario where, during the lonely evenings I wanted to test something out in my home lab environment, because sitting in the hotel bar drinking all night gets a bit tedious...especially when there's no football on. However, I didn't want to be in a position where I had to leave my ESXi hosts running 24×7 just in case I needed to use them when I was on the road and so I needed a way that I could remotely power them on.
The Pi seemed to fit the bill perfectly. I could leave it running all the time without burning a lot of power and if I needed to gain access to my lab environment, I could access the Pi and issue Wake-On-LAN to the ESXi hosts from it. It turns out the little Raspberry Pi is useful for many more things too.
After getting to play with the Pi for a bit, and doing some reading, I came to the conclusion that I could use the device to perform a number of different, useful functions for my home network. Aside from Wake-On-LAN I decided to configure the Raspberry Pi to also perform the following duties:
- VPN Server
- Dynamic DNS Client
Some of these functions were already being performed to a limited extend by my broadband modem and an old Linksys WRT54G wireless router which I'd hacked to run DD-WRT (which, by the way, is very good). I decommissioned the old Linksys and gave it away to a colleague (you're welcome Mike) then disabled services on the Virgin Media Superhub so that it could focus on WiFi and running the Internet connection; something it often struggles with, but I digress. For DHCP and DNS on the Pi I'm using DNSmasq and for the VPN server I'm using OpenVPN. Wake-On-LAN functionality will be provided by a PHP web interface running on Apache and the Dynamic DNS client in use is ddclient.
A number of these services will require either holes poking in the Raspberry Pi firewall (iptables) and either port forwarding or DMZ host configuration on your router. These aspects will be covered in the next article.
I went for the Model B revision 2.0 Raspberry Pi. This has 512MB of RAM and is the latest model available at the time I wrote this article. It cost me just under £27 from eBay merchant New IT Limited. I recommend you buy one of the many Accessory bundles that are available. There are lots of variations to choose from, but I just went for a basic one. The fundamental bits you need are...
- Power adapter (Micro USB B)
- SD Card (8GB or bigger ideally)
- HDMI Cable
You may already have some of these things lying around, so you can always just buy the parts you're missing individually. The accessory bundle I purchased cost just under £24 and provided all of the parts mentioned above. There are more expensive variations available which give you things like USB Wi-Fi adapters and the like but I didn't need any of that.
You'll also need a display with a HDMI input (most modern TVs have this), a USB keyboard and mouse, a CAT5 cable and something to connect it to such as a switch or your broadband router wired LAN ports.
Assemble the Case
I guess this depends on the kind of case you buy, but the one I got was incredibly difficult to assemble. It all just sort of clips together. Each piece relies on every other piece to hold it in place. You need about six hands to do this successfully. Once you're done you should have something like this:
There is a very good setup guide over at http://www.raspberrypi.org/help/noobs-setup/ that covers the initial setup of the device in great detail. If however, you want the abridged version, keep reading.
A lot of the SD cards provided with the Pi accessory bundles come pre-installed with NOOBS (New Out Of Box Software) as did mine. NOOBS is an operating system install manager. It bootstraps the Pi and gives you the option to choose which OS to install. There are a bunch to choose from, but the most commonly used and easiest to find support for is Raspbian (an unofficial port of Debian Wheezy). You can alternatively install an ARM version of ArchLinux, a port of Fedora called Pidora, a minimal RISC OS or a couple of different XBMC media server-based operating systems. There is even an OS dedicated as a vSphere Management Toolbox, called vPI, but this isn't part of NOOBS.
I chose to go with Raspbian, so the rest of this article will focus on the configuration of that particular OS. The SD card I bought had NOOBS pre-installed, but it wasn't the latest version, so I decided to format the card and start fresh.
To do this you'll need the following...
- SD Formatter -- https://www.sdcard.org/downloads/formatter_4/
- Latest version of NOOBS -- http://downloads.raspberrypi.org/NOOBS_latest
- An SD card reader
My work laptop (a Lenovo W510) has a built-in SD Card Reader which I had to use. First, install SD Formatter and then use it to format the SD card. It is recommended that this utility is used as opposed to built-in operating system formatting utilities. Using generic formatting utilities may result in less than optimal performance of the SD card, at least according to the SD Formatter website.
Next, unpack the contents of the NOOBS zip file and copy the contents to the SD Card. Be sure to safely eject the SD Card before removing it from the computer to make sure all write operations have been successfully completed.
Insert the SD Card into the Raspberry Pi. You'll need to hookup the HDMI output to a suitable display. I used an old 19″ Samsung LCD TV which had a HDMI input. Connect a USB keyboard and USB mouse to the two USB ports.
It's a good idea to disconnect the LAN cable from the Raspberry Pi. When I initially tried to setup my Pi, I had the LAN cable connected. The device detected an Internet connection and went off to the web for some unknown reason and this caused the NOOBS setup to hang forever with the message "Please wait while NOOBS initialises".
After disconnecting the LAN and rebooting the device NOOBS worked fine and displayed the OS selection menu. Once you've connected your display, keyboard, mouse and disconnected the LAN, connect the power. Select Raspbian and Data Partition, then click Install.
The installation process took around 40 minutes. The process has to write about 2GB of data on the SD Card and tops out at about 1MB/s, so it takes a little while.
When the process finishes, click OK and the device will reboot.
The Pi will boot up to a text menu with various setup options.
Select the option "Expand Filesystem". This will make sure all of the SD card storage is available to the OS. Set a password for the default user "pi". Configure Internationalisation Options; If you're in the UK Locale needs to be set to en_GB.UTF-8 UTF-8 and timezone to Europe/London.
Under Advanced Options configure the hostname and enable SSH. Back at the main menu, select Finish and then reboot the Pi. Make sure to reconnect the network cable at this point.
Configure a Static IP Address
Don't put the TV away just yet. Login to the Pi as user "pi" with whatever password you specified during initial configuration. You'll need to edit the file /etc/network/interfaces, but to do this you'll need to be root so issue the command; sudo -s then vi /etc/network/interfaces
You need to change the bit that reads: iface eth0 inet dhcp to...
iface eth0 inet static
After modifying the file save and exit vi by typing :wq! and pressing Enter. Restart networking by issuing the command: /etc/init.d/networking restart
Configure DNS Resolution
Although I'll be using DNSmasq to perform name resolution for hosts on my local network, I need the Pi to be able to resolve Internet names too by forwarding queries which it cannot resolve itself out to an Internet name server. For this I'll use Google's public DNS servers. Their IP addresses need to be put into the file /etc/resolv.conf. Edit the file using vi; vi /etc/resolv.conf and set the contents of the file as follows:
DNSmasq provides DNS and DHCP services. It's a lot simpler than trying to set up BIND for DNS and ISC DHCP. While it doesn't offer as many features or flexibility it does everything I need for a small LAN environment. With this configuration, DNSmasq will utilise /etc/hosts and DHCP lease information to provide name resolution. The first thing to do is use apt to install the DNSmasq package:
# sudo apt-get install dnsmasq -y
Once installed you will need to edit the main configuration file:
# vi /etc/dnsmasq.conf
My dnsmasq.conf looks like this, and the directives are explained below...
# DHCP Reservations
dhcp-host=aa:bb:cc:dd:ee:ff,192.168.0.200,desktop,infinite # Main Desktop PC
dhcp-host=11:22:33:44:55:66,192.168.0.201,laptop,infinite # Laptop
- domain-needed: Prevents dnsmasq from forwarding queries for unqualified names
- bogus-priv: Prevents dnsmasq forwarding queries for some non-routed address spaces
- local: Won't forward requests for the local domain specified. This forces core.local names to only be resolved internally.
- server: Causes DNSmasq to forward queries for the domain specified to the IP specified.
- expand-hosts: Automatically append the domain (below) to all /etc/hosts entries.
- domain: Append the specified domain to DHCP hosts, and if expand-hosts directive is used, to hosts using static IPs.
- dhcp-range: From IP, To IP, Subnet Mask, Lease Time.
- dhcp-option=option:router: this specifies the default gateway IP to send to DHCP clients.
- dhcp-authoritative: This should be set when DNSmasq is definitely the only DHCP server on the network (which mine is).
- log-dhcp: Log DHCP messages to /var/log/daemon.log by default; useful for troubleshooting.
- log-queries: Log DNS query messages to /var/log/daemon.log by default; useful for troubleshooting.
The log-dhcp and log-queries directives can be handy when initially setting up DNSmasq for troubleshooting purposes. However, once everything is working as expected, it's a good idea to comment out these directives and restart dnsmasq or force a reload with the commands:
# service dnsmasq restart
# service dnsmasq force-reload
You want to minimize the SD card writes to prolong its life, so disabling unnecessary logging is a good place to begin.
The last section of /etc/dnsmasq.conf is used for DHCP Reservations. You're supposed to be able to add DHCP reservation information into the file /etc/ethers and using the read-ethers directive, instruct DNSmasq to pull the information from there. However, in my experience this didn't work as expected and devices that should have had DHCP reservations were just pulling a random IP from the DHCP range. To rectify this I added the relevant dhcp-host directives directly into /etc/dnsmasq.conf and removed the read-ethers directive.
The format of the dhcp-host entries is as follows:
So, for example, the entry...
dhcp-host=aa:bb:cc:dd:ee:ff,192.168.0.200,desktop,infinite # Main Desktop PC
...will lease the IP address 192.168.0.200 to the device with MAC address aa:bb:cc:d:ee:ff with a hostname of desktop for an infinite duration. Everything after the hash (#) is simply a comment.
Network Time Protocol (NTP) is an incredibly important and often overlooked (especially in lab environments) service to have available. Clustering software and authentication methods often rely on hosts keeping accurate time. First the package must be installed...
# sudo apt-get install ntp -y
The only configuration change that needs to be made to get a basic NTP service working, is a restrict directive in /etc/ntp.conf
# Clients from this (example!) subnet have unlimited access, but only if
# cryptographically authenticated.
#restrict 192.168.123.0 mask 255.255.255.0 notrust
restrict 192.168.0.0 mask 255.255.0.0 nomodify notrap
The line restrict 192.168.0.0 mask 255.255.0.0 nomodify notrap is what allows hosts on the 192.168.0.0/16 subnet to connect to the NTP server and synchronise their clocks.
Start the NTP service with the command:
# service ntp start
Configure OpenVPN Server
There is a very in-depth write-up on how to configure the OpenVPN server and client by Lauren Orsini over at readwrite.com. While it is very detailed, it seems to be aimed at people with little to no experience of using a Linux command line interface, so if you want the condensed version, keep reading.
Switch to the root user so you don't keep having to put ‘sudo‘ at the beginning of every command.
# sudo -s
Update the Raspberry Pi software.
# apt-get update
# apt-get upgrade
Next you'll need to install the OpenVPN server package.
# apt-get install openvpn -y
Copy the Easy_RSA files to the OpenVPN configuration directory.
# cp -r /usr/share/doc/openvpn/examples/easy-rsa/2.0 /etc/openvpn/easy-rsa
# cd /etc/openvpn/easy-rsa
Edit the file vars and change the EASY_RSA variable so it reads:
Source the var file to load variables into memory:
# source ./vars
If you've already attempted the process and made a mistake, you can clean up any previously configured keys. If this is your first go, then you can skip this command:
Now build the new Certificate Authority:
Fill in the fields that are presented. You'll need to specify a 2 letter country code, state or province name, locality name, organisation name, organisational unit name, common name, name and email address. You can put whatever you like in these fields, or just ENTER through them to accept the defaults. As you're going to end up creating a self-signed certificate it doesn't really matter.
Next, run the command:
# ./build-key-server [server-name]
You can specify whatever you like for [server-name] provided it is at least six characters. Whatever you decide to call it, make sure you remember what you entered. I suggest sticking with something simple like "server". Again, you're going to be prompted to fill in a bunch of fields. Put in whatever values you want or just ENTER through them and accept the defaults, but make sure to specify the following values for these three important fields:
- Common Name -- MUST match the value you specified for [server-name], which it should default to.
- A challenge password -- This MUST be left blank.
- Sign the certificate -- Answer Y (yes).
You'll then receive the message: 1 out of 1 certificate requests certified, commit [y/n]. Type "y" and press ENTER.
Next you'll need to build keys for each client user.
# ./build-key-pass [username]
Where [username] is going to become the username for your OpenVPN client account. Specify the client password (make it something secure that you'll remember) and then answer "y" to Sign the certificate?
# cd keys
# openssl rsa -in [username].key -des3 -out [username].3des.key
At this point we're encrypting the client key using Triple DES. You'll be prompted for another passphrase. The next step is to build the Diffie-Hellman key exchange. This process can take a few minutes to complete.
# cd /etc/openvpn/easy-rsa
Next, we'll generate a static HMAC key. This allows us to implement OpenVPN's built-in DDoS prevention.
# openvpn ---genkey --secret keys/ta.key
* Worpress is messing with the formatting, that's double hyphen before genkey and secret...
We need to edit the OpenVPN server configuration at this point...
# vi /etc/openvpn/server.conf
The contents should be as follows:
proto udp # Default protocol is UDP, this can be changed to TCP if you've a specific requirement
port 1194 # Default port number is 1194, again this can be changed if required.
cert /etc/openvpn/easy-rsa/keys/Server.crt # Replace with your .crt name
key /etc/openvpn/easy-rsa/keys/Server.key # Replace with you key name
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.0.0 255.255.255.0" # This should be your local network's subnet
push "dhcp-option DNS 192.168.0.254" # I'm using my Pi for DNS, so I'm specifiying it's IP here. Replace with whatever device is doing DNS for you or use Google's Public DNS at 188.8.131.52
# Override the Client default gateway by using 0.0.0.0/1 and
# 184.108.40.206/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"
keepalive 10 120
tls-auth /etc/openvpn/easy-rsa/keys/ta.key 0
status /var/log/openvpn-status.log 20
We need to enable ip_forwarding on the Pi, as it's going to act as a router for VPN clients...
# vi /etc/sysctl.conf
Look for the line that contains:
Set it to...
Make sure to uncomment the line.
Force the kernel to reload configuration parameters:
# sysctl -p
The last step on the server configuration is to poke some holes in the IPtables firewall. To do this we'll need to create a script with iptables commands in it that will be run each time the network interface is brought online.
# vi /etc/firewall-openvpn-rules.sh
Add the following contents to the file...
iptables -t nat -A POSTROUTING -s 10.8.0.0/24 -o eth0 -j SNAT --to-source 192.168.0.254
All we're doing here is getting IPtables to NAT the IP of any any incoming VPN clients so that to other devices on the local LAN it appears that the traffic is coming from the Raspberry Pi itself, otherwise the other hosts wouldn't know how to get back to a client from the 10.8.0.0 network as only the Pi knows about it as part of the OpenVPN configuration. Obviously, if you're Pi isn't on 192.168.0.254 then you'll need to change the --to-source IP address to match the IP of your Pi.
Set the permissions and ownership of the script:
# chmod 700 /etc/firewall-openvpn-rules.sh ; chown root /etc/firewall-openvpn-rules.sh
We need these rules to be activated any time the network interface comes up. To achieve this, we need to add the following line to /etc/network/interfaces
Add it under the gateway entry for eth0. The file should look like this...
iface lo inet loopback
iface eth0 inet static
iface wlan0 inet manual
iface default inet dhcp
Now reboot the Pi:
# sudo shutdown -r 0
Configuring Dynamic DNS Client
If you're ISP doesn't give you a static IP address (and they probably don't), then it's a good idea to create a dynamic DNS account. The idea is, that instead of having to remember your public IP address, which could change periodically, you register an easy to remember domain name with one of the numerous dynamic DNS providers and then use a Dynamic DNS client, to keep the IP address that the domain points to updated.
There are a number of dynamic DNS providers who'll let you register a domain for free. I'm using DNSdynamic.org. Creating an account with them is simple. Pick from one of their many domains...
Then type in a subdomain of your choice. So, for example, you could go for something like "myvpn.dnsget.org". Click on Check Availabiliy. If the domain is not available, you'll have to keep trying untill you can find something that is. Once you've found something, sign-up for free and create yourself an account.
You'll then need to install the Dynamic DNS Client for Raspbian, ddclient:
# sudo apt-get install ddclient -y
Edit the default configuration file /etc/ddclient.conf:
# vi /etc/ddclient.conf
You'll want the content to look something like that shown below. Obviously, if you choose to go with a different dynamic DNS provider, the settings will most likely be slightly different. Many of the providers have excellent documentation on their websites which will tell you how you need to configure ddclient.
Save and exit the file, and then restart the ddclient service:
# service ddclient restart
Configure OpenVPN Clients
You should have a working OpenVPN server up and running now, and a dynamic DNS client keeping your public IP mapped to an easy to remember domain name. The next thing that needs to be done is to configure the client side of the VPN. First we'll create a file with a bunch of default settings that will be used for every client configuration.
# cd /etc/openvpn/easy-rsa/keys
# vi default.txt
Populate the file with the following...
proto udp # change this to TCP if that's what you set in your /etc/openvpn/server.conf
remote your.dynamic.domain 1194 # set your dynamic domain name or public IP. If you specified a different port in your /etc/openvpn/server.conf, specify that port number instead of 1194
If you're not using a dynamic domain name, and you just want to use your public IP address, the easiest way to find out what it is, is by visiting www.whatsmyip.org.
There is quite a bit of work to do to create the .ovpn files used by the OpenVPN client. Luckily for us, Eric Jodoin of the SANS Institute has written a script which takes care of it. The original script can be found here. A copy of the current script content is below.
# Default Variable Declarations
#Ask for a Client name
echo "Please enter an existing Client Name:"
#1st Verify that client’s Public Key Exists
if [ ! -f $NAME$CRT ]; then
echo "[ERROR]: Client Public Key Certificate not found: $NAME$CRT"
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"
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"
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"
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 "<ca>" >> $NAME$FILEEXT
cat $CA >> $NAME$FILEEXT
echo "</ca>" >> $NAME$FILEEXT
#Next append the client Public Cert
echo "<cert>" >> $NAME$FILEEXT
cat $NAME$CRT | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' >> $NAME$FILEEXT
echo "</cert>" >> $NAME$FILEEXT
#Then, append the client Private Key
echo "<key>" >> $NAME$FILEEXT
cat $NAME$KEY >> $NAME$FILEEXT
echo "</key>" >> $NAME$FILEEXT
#Finally, append the TA Private Key
echo "<tls-auth>" >> $NAME$FILEEXT
cat $TA >> $NAME$FILEEXT
echo "</tls-auth>" >> $NAME$FILEEXT
echo "Done! $NAME$FILEEXT Successfully Created."
#Script written by Eric Jodoin
You should be able to copy and paste the above script into a new file on the Raspberry Pi:
# vi MakeOVPN.sh
Paste in the contents. When copying, be sure you don't accidentally select the line numbers too. Give the script execute permissions:
# chmod 700 MakeOVPN.sh
Now execute the script:
When the script runs, it will prompt you to enter the names of the existing clients for which you eariler generated keys. If successful, the script should produce the message:
Done! [username].ovpn Successfully Created.
Repeat this step for each client you set up. You now need to download the .ovpn files from your Raspberry Pi. The easiest way to do this, is to copy them to the home directory of the account you use to login to the Pi. If you're using the default account "pi" just run the command:
# cp *.ovpn ~pi
Make sure the files have read permissions for everyone, so you can actually download them:
# cd ~pi
# chmod o+r *.ovpn
Now, connect to the Pi using a client such as WinSCP. Login, browse to the home directory you copied the .ovpn files to and download them to your local machine. You can now use these files to configure the OpenVPN Windows client or cilents for iOS, Android or Mac. Depending on the client you use, the setup process for getting the .ovpn into the application might be slightly different. Check out your OpenVPN client documentation for details on how to accomplish this.
OpenVPN Client on Windows 7 with UAC
One thing to note; if you plan on using the OpenVPN client on a Windows 7 machine that has UAC enabled, one thing I've noticed is that if you just run the client and connect, your routing table will not be properly updated. To get it to work correctly, you need to modify the OpenVPN client shortcut to Run as Administrator. Each time you launch it, the UAC warning will pop up which you'll have to accept, but it seems to be the only way to give it the permissions it needs to make changes to the routes.
The original primary purpose of the Pi was to perform WOL duties for hosts on the local network. There's an excellent article and the relevant software required available for download at Jeremy Blum's blog. The specific article can be found here.
The article covers some other aspects of the setup such as configuring your router for port forwarding, dynamic DNS and figuring out your host MAC addresses. Some of these steps will not be neccessary if you're been following my guide as we're doing things in a slightly different order. We've already configured dynamic DNS and as for port forwarding, I'll be covering that in the next article.
The gist of what you need to do to get Wake-On-LAN setup, which I'm paraphrasing from Blum's post is as follows:
# sudo -s
# apt-get install wakeonlan apache2 php5 git -y
# git clone https://github.com/sciguy14/Remote-Wake-On-LAN-Server.git
# chown pi:pi /var/www
# mv Remote-Wake-On-LAN-Server/* /var/www
# rm -rf Remote-Wake-On-LAN-Server
# rm -f /var/www/index.html
# mv /var/www/config_sample.php /var/www/config.php
# vi /var/www/config.php
Configure the contents of the file config.php as directed by the instructions within. Essentially, you need to specify hostnames, IP addresses and MAC addresses of the device you want to be able to perform remote Wake-On-LAN for as well as set the SHA256 hash of a passphrase you choose that must be entered before a Wake-On-LAN command can be issued.
Securing Hardening & Internet Access
As you'll be hosting Internet facing services on the Raspberry Pi, the next thing you need to do is secure it. You may have noticed that I have not covered things like port forwarding yet. You don't want to open up access to the Pi via your broadband router just yet, not until you've locked things down a little bit.
There are a couple of different approaches I've taken to making the Pi more secure. Apart from the OpenVPN server, I also have SSH and Apache services running which I want to be accessible from the Internet.
In the next article I will be looking at ways of making the Raspberry Pi more secure before finally opening up access to it from the Internet.