Raspberry Pi OpenVPN is a great way to access a home network from a remote location. In addition it can be used to secure network communications when connecting to public Wi-Fi. Since the RPi is very low-powered single board computer it is ideal for setup your own Raspberry VPN server with OpenVPN. OpenVPN comes with Easy_RSA, a simple package for using the RSA encryption. Let’s find out how you can how to setup OpenVPN on Raspberry Pi device.
Why VPN?
One possible scenario for wanting your own VPN server that while you are away from home and would like to be able to access all devices on the network at home in a secure manner and you can use public Wi-Fi but you can secure your connection to the world. VPN act as a secure tunnel that start from your device to your VPN server.
This tutorial is based on Raspbian Linux version 7 (wheezy), Raspberry Pi B/B+/2/3
Update Pi OS and Firmware
Lets update raspberry pi OS and firmware by issuing following two commands from shell, i prefer to use Putty but its up to you what ever you want to use to remote connect your Raspberry Pi.
1 2 |
sudo apt-get update sudo apt-get upgrade |
Install OpenVPN server.
Enter following command to begin the openvpn installation.
1 |
sudo apt-get install openvpn -y |
Generating Keys
OpenVPN comes with easy_rsa, a light and easy package for using the RSA encryption method. This is what makes your VPN connection safe. if easy-ras isn’t installed then you can do so by running following command.
1 2 3 |
git clone https://github.com/OpenVPN/easy-rsa.git cd easy-rsa git checkout 2.2.2 |
You will know if it worked if it says this at the bottom of the window:
1 |
"HEAD is now at 19c3186... creating 2.x branch for tracking changes" |
Lets copy RSA to OpenVPN and make some changes
1 2 |
cp -r easy-rsa/2.0/ /etc/openvpn/easy-rsa cd /etc/openvpn/easy-rsa |
You need to make some changes to easy-ras, edit vars file
1 2 |
vi vars export EASY_RSA="`pwd`" |
Change this to:
1 |
export EASY_RSA="/etc/openvpn/easy-rsa" |
Now you can change key size from 1024 to 2048, simple scroll down using the arrow keys and locate export key_size
1 |
export KEY_SIZE=1024 |
Change this to:
1 |
export KEY_SIZE=2048 |
Now save the file and exit.
Build Encryption Certificates
Enter following command one at a time
1 2 3 |
source ./vars ./clean-all ./build-ca |
Enter all relevant information, this could take some time to finish.
Server Certificate
Now we’ll create a certificate for and name the server. I named mine vpn.pihome.eu but it really doesn’t matter.
1 |
./build-key-server <your server name> |
Enter all relevant information and make sure you don’t enter anything for a challenge password it must be left blank, once server certificate is created it would stay valid for 10 years.
Client Certificate
Now you can create certificate for each client or you can generate one certificate and use this on all clients. run following command, you can use any user you want to use, make sure you enter the username that you can easily remember.
1 |
./build-key-pass <username> |
You can enter all default values but password for Enter PEM pass phrase that you can remember, this will be used every time you connect to your Raspberry pi OpenVPN server.
DS3 Encryption Scheme
Now we need to change the keys to an ds3 encryption scheme.
1 2 |
cd keys openssl rsa -in pihome.key -des3 -out pihome.3des.key |
Enter the Enter pass phrase for pihome.key: as you did in previous step.
Enter PEM pass phrase: as as previous and then Verifying – Enter PEM pass phrase:
Diffie-Hellman Keys for Your Server
Now we will generate the Diffie-Hellman keys for your server. This will allow your clients and the server to exchange keys.for more on Diffi-Hellman see wiki page
Now change directories back to /etc/openvpn/easy-rsa/:
1 |
cd .. |
Lets generate Diffie-Hellman keys for your server. This process will take very long time so best to get coffee and sit back and enjoy your coffee.
1 |
./build-dh |
DDoS Protection
OpenVPN has built in DDoS Protection so all you’ll need to do is run this command
1 |
openvpn --genkey --secret keys/ta.key |
OpenVPN Server Configuration
Now we need to configure OpenVPN Server to get connected. You need to create server.conf file and copy and paste my server.conf settings, you can modify as you need.
1 |
vi /etc/openvpn/server.conf |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
dev tun proto udp # i prefer udp port but you can change this to tcp. port 1194 # this is default port for openvpn you can change this to any thing you want. ca /etc/openvpn/easy-rsa/keys/ca.crt cert /etc/openvpn/easy-rsa/keys/pihome.crt key /etc/openvpn/easy-rsa/keys/pihome.key dh /etc/openvpn/easy-rsa/keys/dh2048.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.99.9 255.255.255.0" # change this with your raspberry pi ip address. push "route 192.168.9.0 255.255.255.0" # change this to your home network range. # Set primary domain name server address to the SOHO Router # If your router does not do DNS, you can use Google DNS 8.8.8.8 push "dhcp-option DNS 8.8.8.8" push "dhcp-option DNS 8.8.4.4" #push "redirect-gateway autolocal" 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 management 127.0.0.1 45678 |
Network Config for OpenVPN
By Default network traffic forwarding isn’t enabled. you can simply enable this by modifying /etc/sysctl.conf and un-commenting #net.ipv4.ip_forward=1 line
1 2 3 |
vi /etc/sysctl.conf # Uncomment the next line to enable packet forwarding for IPv4 net.ipv4.ip_forward = 1 |
Now apply these changes with following command
1 |
sysctl -p |
iptables for Raspberry pi OpenVPN
OpenVPN server is fully configured but raspberry pi OS comes with built-in firewall and it blocks all incoming connections. rung following commands and make sure you don’t get any errors.
1 2 3 4 5 6 7 8 9 |
sudo /sbin/iptables -P FORWARD ACCEPT sudo /sbin/iptables --table nat -A POSTROUTING -o wlan0 -j MASQUERADE iptables -A INPUT -i wlan0 -m state --state NEW -p udp --dport 1194 -j ACCEPT iptables -t nat -A INPUT -i wlan0 -p udp -m udp --dport 1194 -j ACCEPT iptables -A FORWARD -i tun+ -o wlan0 -m state --state RELATED,ESTABLISHED -j ACCEPT iptables -A FORWARD -i wlan0 -o tun+ -m state --state RELATED,ESTABLISHED -j ACCEPT iptables -A INPUT -i tun+ -j ACCEPT iptables -A FORWARD -i tun+ -j ACCEPT iptables -A OUTPUT -o tun+ -j ACCEPT |
if above two lines don’t give you any error then you are good so far. Create sh file and copy and paste below text to.
1 |
vi /var/www/cron/iptables_allow.sh |
1 2 3 4 |
#!/bin/bash sudo /sbin/iptables -P FORWARD ACCEPT sudo /sbin/iptables --table nat -A POSTROUTING -o wlan0 -j MASQUERADE sudo iptables-save |
Make this script executable by issuing following command.
1 2 3 |
chmod +x /var/www/cron/iptables_allow.sh chmod 700 /var/www/cron/iptables_allow.sh chown root /var/www/cron/iptables_allow.sh |
Now you need to create symbolic link to this file in /etc/init.d/
1 |
ln -s /var/www/cron/iptables_allow.sh /etc/init.d/iptables_allow.sh |
Raspberry pi OpenVPN Client Configuration – Export OVPN
First create Default.txt file at /etc/openvpn/easy-rsa/keys/, copy and paste below to this file and save it. make sure you add your public ip or ddns hostname.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
client dev tun proto udp remote <your public ip or ddns hostname> 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 |
Second step to export client settings that are usable on any smart phone or desktop/laptop computer. create makeovpn.sh in /etc/openvpn/easy-rsa/keys and copy paste below script to this file.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 |
#!/bin/bash # ref: https://gist.github.com/coolaj86/4120d90e57d1d01cd59f # Default Variable Declarations DEFAULT="Default.txt" FILEEXT=".ovpn" CRT=".crt" KEY=".3des.key" NODES_KEY=".key" CA="ca.crt" TA="ta.key" NAME="${1}" if [ -z "${NAME}" ]; then # Ask for a Client name echo "Please enter an existing Client Name:" read NAME fi #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 "[INFO]: Client 3des Private Key not found: $NAME$KEY" KEY="${NODES_KEY}" fi if [ ! -f $NAME$KEY ]; then echo "[ERROR]: Client 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 "<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 |
Change directory to /etc/openvpn/easy-rsa/keys and make makeovpn.sh file executable make sure you run this script from /etc/openvpn/easy-rsa/keys otherwise you will get error message and exporting of OVPN wouldn’t work.
1 2 3 4 |
cd /etc/openvpn/easy-rsa/keys/ chmod +x makeovpn.sh sh ./makeovpn.sh Enter Username that you want to export settings for. |
Repeat this for this process for all the users you have created. OVPN extension file will be saved with same name as you have username in /etc/openvpn/easy-rsa/keys/ you can use winscp or any other client to copy these files out.
If you need help for Installing Linux OS (Raspbian Jessie) on Raspberry Pi see this link
4 comments
Hi,
i use two virtual interface (static ip, dhcpcd service disabled) eth0 and eth0:0 on the same physical ethernet – the first for public internet access, the second to connect mobile apps back to the raspberry from the public internet, or connect via ssh (dyndns, port forwarding).
It’s possible to bind the openvpn client to one of the virtual interfaces (ex. eth0:0)?
Thx
@Peter i dont see that as problem, all you have to do is modify your server.conf file and iptables for that interface.
Would you be able to update this article for Rasbian Stretch, or has the proces remained unchanged?
Hi Andrew, i dont see any reason for any major changes but i haven’t tested this on Rasbian Stretch. you can give it try and let me know if these steps down works.