In this blog post we will look at creating a VPN on a Raspberry Pi. So why use a VPN well if you travel a lot, or live outside your home country, or if your like me and don’t want to miss your country annihilate the opposition at Rugby, are security conscious, or would like to keep your IP address located in your home country, using a VPN is a viable option. Even better hosting your VPN on a Raspberry Pi offers a cheap and efficient solution when compared to other options.
In this post we will perform the following tasks:
The first thing we are going to do is setup our Raspberry Pi with an operating system.
The first thing we need to do is install Arch Linux on the Raspberry Pi. So firstly head over to the arch linux downloads page and download the latest version of arch linux.
1 | https://www.archlinux.org/download/
|
Next we need to insert the SD card into the SD card drive and find the card name using the lsblk command.
1 | lsblk
|
After running the command you should see output similar to the below:
1 2 3 4 | NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
...
sdc 8:16 1 59.6G 0 disk
...
|
In the above output the name of the SD device is /dev/sdc but this can be different on your system. Next we will use parted utility to format the drive and create the required partitions. Firstly create the partition table by running the command :
1 | sudo parted /dev/sdc --script -- mklabel msdos
|
Next run the command to create the partitions:
1 | sudo parted /dev/sdc --script -- mkpart primary fat32 1 128sudo parted /dev/sdc --script -- mkpart primary ext4 128 100%
|
Next add the bootable flag to the boot partition:
1 | sudo parted /dev/sdc --script -- set 1 boot on
|
Next to confirm that everything is setup correctly we will print the partition table to the console:
1 | sudo parted /dev/sdc --script print
|
The output should look something like:
1 2 3 | Number Start End Size Type File system Flags
1 1049kB 128MB 127MB primary boot, lba
2 128MB 64.0GB 63.9GB primary
|
Next we will format the boot partition to FAT32:
1 | sudo mkfs.vfat -F32 /dev/sdc1
|
Next we must format the root partition:
1 | sudo mkfs.ext4 -F /dev/sdc2
|
Now that the SD card is setup we need to start the installation process of Arch Linux. First we will need to mount the partition and copy the distribution files.
First we will create the directories that will serve as the mount points.
1 | sudo mkdir -p /mnt/arch/{boot,root}
|
Next we will mount the partitions:
1 2 | sudo mount /dev/sdc1 /mnt/arch/boot
sudo mount /dev/sdc2 /mnt/arch/root
|
Next use the tar command to extract the contents of the Arch Linux distribution to the /mnt/arch/root directory:
1 | sudo tar -xf <ARCH_LINUX_DISTRIBUTION> -C /mnt/arch/root
|
Next we need to move the boot files to the mounted boot partition.
1 | sudo mv /mnt/arch/root/boot/* /mnt/arch/boot
|
Next unmount the partitions:
1 | sudo umount /mnt/arch/boot /mnt/arch/root
|
To boot the Raspberry PI put the SD card into the Pi and plug in any peripherals such as keyboard, monitor etc. Next login to your Raspberry Pi using the user root and the password root. Once logged in you can change your password etc, but for the purposes of this tutorial we will leave them as root.
Finally you will want to initialize the package manager and update the system.
1 2 | pacman-key –init
pacman-key --populate archlinuxarm
|
If you haven’t already done so please login to the Raspberry Pi using the user root and the password root.
Next we will ensure our system is current by executing a system update.
1 | pacman -Syu
|
Next we will install some of the packages that we will use in this post. Run the following commands:
1 | pacman -S noip netcfg bridge-utils openvpn
|
Answer y to any prompts that you may encounter. Once the above packages are installed we will configure the network.
We need to configure a client to site bridge because we will be connecting the VPN client to the servers network. Therefore, the servers subnet must be different from the clients subnet. For example the network subnet at your home could be 192.168.1.0/24. If the subnet of the server has the same subnet 192.168.1.0/24 the network would have problems routing traffic because it would not know if the network address was referring to the home network or the VPN server.
In this case we must ensure that the home network and the VPN are on different subnets. For this reason it is recommend to pick a non standard subnet. You should we able to change your home subnet by configuring your home router with a non standard subnet so it does not matter what the servers subnet is. However, you still might want to change the servers subnet as you may want to connect from a public Wi-Fi that uses a standard subnet. It is recommend to change your servers subnet by picking a /24 subnet which has the subnet mask:
1 | 255.255.255.0
|
in one of the private address ranges:
Next we will setup a static IP for the VPN server running on the Raspberry Pi. Setting up a static IP has the advantage that you will always know where to access your Raspberry PI when you need to access it remotely. In order to do this we will use the Arch Linux netcfg command to manage our network connections. We will need to setup three different network connections:
First we need to change the directory:
1 | cd /etc/network.d
|
Next we need to open a new file name bridge:
1 | nano bridge
|
With the file bridge opened enter the network configuration below changing the network settings with your own:
1 2 3 4 5 6 7 8 9 | INTERFACE=”br0”
CONNECTION=”bridge”
DESCRIPTION=”VPN Bridge Connection”
BRIDGE_INTERFACE=”eth0”
IP=”static”
ADDR=’192.168.1.220’
NETMASK=’24’
GATEWAY=’192.168.1.254’
DNS=(‘192.168.1.254’)
|
One you have entered the above interface save the file using Ctrl + O followed by Enter and then exit nano using Ctrl + X.
Next we need to configure the profiles netcfg will load by editing /etc/conf.d/netcfg.
1 | nano /etc/conf.d/netcfg
|
Add or change the NETWORKS array to:
1 | NETWORKS=(bridge)
|
Save the file using Ctrl + O followed by Enter and then exit nano using Ctrl + X. Next we will run the commands to disable DHCP. We will also enable the ethernet interface and the bridge with a static IP.
1 2 | systemctl disable dhcpcd@eth0.service
systemctl enable netcfg.service
|
Now restart the Pi for the changes to take effect. When the Raspberry Pi comes back up login with SSH using the password root unless you changed it:
1 | ssh root@<PI_IP_ADDRESS>
|
Next change your root password using the passwd command picking a secure password.
1 | passwd
|
You can also change the host name of your VPN server by editing the /etc/hostname file. This is a good idea to make it easier to identify the server.
Next we are going to setup the public key infrastructure using a certificate to authenticate OpenVPN. We will generate a certificate and a private key that you should keep private for each client. The certificate and the key are used to encrypt the traffic sent between the client and the VPN server. First we need to copy the scripts to /etc/openvpn.
1 2 | cp -r /usr/share/openvpn/easy-rsa/ /etc/openvpn
cd /etc/openvpn
|
Next we are going to create a template to base our certificate on.
1 | nano vars
|
Change the lines at the end of the file to something like:
1 2 3 4 5 6 7 8 | export KEY_COUNTRY=”IE”
export KEY_PROVINCE=””
export KEY_CITY=”Dublin”
export KEY_ORG=”Home”
export KEY_EMAIL=”stephen@vpn.myhome.org”
export KEY_CN=”stephenvpn-ca”
export KEY_NAME=”stephenvpn-ca”
export KEY_OU=”None”
|
Save the file using Ctrl + O followed by Enter and then exit nano using Ctrl + X, then export the variables:
1 | source ./vars
|
Next clean any previous configuration:
1 | ./clean-all
|
Next we will create the certificates. First we will generate the authority certificate that we will use to sign the rest.
1 | ./build-ca
|
Next we will generate the server certificate using the server host name.
1 | ./build-key-server <SERVER HOST NAME>
|
If asked for any information press enter, and don’t fill in a password or company name. Also, accept the request to sign the certificate. Next we will generate the Diffe-Hellman parameters needed to allow the exchange of a secret key.
1 | ./build-dh
|
Next you must generate a certificate for each client that you would like to connect to OpenVPN. In this case we will generate a key for stephen’s laptop.
1 | ./build-key stephen-laptop
|
Next we will configure the OpenVPN Server.
1 | cp /usr/share/openvpn/examples/server.conf /etc/openvpn/server.conf
|
Above we copy an example server configuration that we will configure below:
1 | nano /etc/openvpn/server.conf
|
Make the following changes to the file by changing:
1 2 | ;dev tap
dev tun
|
to:
1 2 | dev tap0
;dev tun
|
We make the above changes because we want to use a tap adapter which allows us to bridge the network rather than creating a tunnel. Next replace the certificates that you created.
1 2 3 4 | ca ca.crt
cert server.crt
key server.key # This file should be kept secret
dh dh1024.pem
|
With the ones we created which is something like:
1 2 3 4 | ca /etc/openvpn/easy-rsa/keys/ca.cert
cert /etc/openvpn/easy-rsa/keys/stephenvpn.crt
key /etc/openvpn/easy-rsa/keys/stephenvpn.key
dh /etc/openvpn/easy-rsa/keys/dh1024.pem
|
Also comment out the line by place a semicolon in front of it:
1 | server 10.8.0.0 255.255.255.0
|
to:
1 | ;server 10.8.0.0 255.255.255.0
|
Also uncomment the below line as we want to use a ethernet bridge rather than a regular server.
1 | server-bridge 10.8.0.4 255.255.255.0 10.8.0.50 10.8.0.100
|
Also after you uncomment the above line you need to change the values to match your servers configuration, fill in the appropriate values replacing the placeholders.
1 | server-bridge <Server IP> <Server Subnet Mask> <Server Start Ip Range> <Server End IP Range>
|
Finally uncomment the lines:
1 2 | ;user nobody
;group nobody
|
to
1 2 | user nobody
group nobody
|
Save the file using Ctrl + O followed by Enter and then exit nano using Ctrl + X.
Next we will configure the Tap interface.
1 | nano /etc/network.d/tap
|
Add the following lines to the file:
1 2 3 4 5 | INTERFACE=’tap0’
CONNECTION=’tuptap’
MODE=’tap’
USER=’nobody’
GROUP=’nobody’
|
Save the file using Ctrl + O followed by Enter and then exit nano using Ctrl + X. Next we need to configure our bridge with the tap interface.
1 | nano /etc/network.d/bridge
|
Change the bridge interfaces line to look like:
1 | BRIDGE_INTERFACES=”eth0 tap0”
|
Save the file using Ctrl + O followed by Enter and then exit nano using Ctrl + X. Next we need to configure netcfg.
1 | nano /etc/conf.d/netcfg
|
Change the NETWORKS variable to:
1 | NETWORKS=(tap bridge
|
Save the file using Ctrl + O followed by Enter and then exit nano using Ctrl + X.
Next we must enable OpenVPN:
1 | systemctl enable openvpn@server
|
Now reboot the Raspberry Pi and make sure that everything starts up as expected.
Now that the OpenVPN server is configured we will now configure Dynamic DNS so we can access our VPN server from anywhere using a easy to remember domain name. Go to the no-ip website and create an account for the No-IP free option.
1 | www.no-ip.com/personal
|
Once you have activated your account by clicking the link in the sign up email that you will receive from no-ip, login to your no-ip account and add a new host. You must choose a host name and a domain. Select the host type as DNS Host and the click the create host button. For example I entered the host name stephen-home with the domain no-ip.org so that I can access the VPN server from stephen-home.no-ip.org.
With are account created we now need to configure the no-ip daemon on our Raspberry Pi. The no-ip daemon will update the no-ip account we created in the last step mapping the router IP address to the domain name we created with the no-ip service. From the command line on our Raspberry Pi enter:
1 | noip2 -C -Y
|
This will start the interactive configuration. In my case I left the update interval at 30 minutes which means the no-ip daemon will push the VPN Server public IP address every 30 minutes to the no-ip account. Once you have completed the configuration steps we must start the daemon.
1 | /etc/rc.d/noip start
|
After a couple of minutes the VPN public IP address will be accessible from the no-ip host name.
Next we need to configure NAT port forwarding to allow your devices behind your router to share the same IP4 address, and also it is more secure to segregate your home network from the Internet. NAT works by forwarding a port from the routers external IP address to a device on the LAN. What we want to do is forward port 22 used for SSH that comes to the routers external IP address to the Raspberry Pi. We will also forward UDP port 1194 as this is used by OpenVPN. To configure port forwarding you will have to use your routers configuration which will depend on the router that you are using.
I am currently using Ubuntu so I will setup an Ubuntu client to connect to the OpenVPN server running on the Raspberry Pi.
1 2 | sudo apt-get update
sudo apt-get install network-manager-openvpn-gnome
|
Once the OpenVPN client is installed we need to copy the certificates that we created for stephens laptop in a previous step. We will use SCP to copy the files into /etc/openvpn/keys directory
1 2 3 4 5 6 7 | cd /etc/openvpn
sudo mkdir keys
cd keys
sudo scp root@[IP Address Of Pi]:/etc/openvpn/easy-rsa/keys/ca.cert .
sudo scp root@[IP Address Of Pi]:/etc/openvpn/easy-rsa/keys/stephenlaptop.cert .
sudo scp root@[IP Address Of Pi]:/etc/openvpn/easy-rsa/keys/stephen-laptop.key .
sudo chmod +r *
|
Next we create the VPN connection by clicking on the Network Icon on the top menu bar of Ubuntu. Click on Edit Connections, then click on the VPN tab and click add. Select OpenVPN as a connection type and the click create, and fill in the appropriate information.
We also need to set the advanced settings, so set:
Finally, set the option to “Use this connection only for resources on its network”. To do this you must go to the IPv4 Settings tab and click on the Routes button. Tick the box with the option “ Use this connection only for resources on its network” and save your connection and close the network connections dialog.
Now you can connect to your VPN server, by clicking on the Network Icon in the top menu bar of Ubuntu then hover over VPN connections and select the VPN connection that you just created.