personal blog
git clone git://
Log | Files | Refs | README (9585B)

      1 As mentioned in my previous [post](/content/20170503-raspberry_pi_setup.html), I want to use my Raspberry Pi as a VPN server. If you followed along with the install guide you should have a basic Raspbian OS running on your Pi. You may have installed other software, or configured the Pi however you prefer. If you have made any changes it _may_ alter the following VPN setup.
      3 For this guide I will be continuing on with the basic install as it was after the previous post.
      5 _Note_ - Using a VPN from outside your home network will require port forwarding on your router. Through the router admin console you should be able to forward all traffic to your Pi's 'tun0' device, which is created later. You will also need your external IP address. Use a site such as [](
      7 ## Open(VPN) your world
      9 There are a number of VPN server options out there, but the most popular is [OpenVPN]( It is incredibly easy to install, and works with the default configuration. There is a web based management console which enables you to adjust the settings quickly.
     11 First things first, let's make sure our Pi is up to date then we can install OpenVPN. We will also install `easy-rsa`, OpenVPN's CA utility
     12 ```
     13 sudo apt update
     14 sudo apt upgrade
     15 sudo apt install openvpn easy-rsa
     16 ```
     18 As root copy config file from OpenVPN's example files. If the command doesn't work with sudo, run as root as shown below (needs root password)
     19 ```
     20 cd /usr/share/doc/openvpn/examples/sample-config-files/
     21 su -c "gunzip -c server.conf.gz > /etc/openvpn/server.conf"
     22 ```
     24 Open the config file for editing
     25 ```
     26 sudo vi /etc/openvpn/server.conf
     27 ```
     29 Change the Diffie hellman parameter from 1024 to 2048
     30 Before
     31 ```
     32 dh dh1024.pem
     33 ```
     34 After
     35 ```
     36 dh dh2048.pem
     37 ```
     39 Remove comment (';') from the DHCP redirect line
     40 ```
     41 push "redirect-gateway def1 bypass-dhcp"
     42 ```
     44 Remove comment (';') from the two DNS lines. If you want to change the DNS servers edit the IP addresses on these lines. I have opted to stick with the defaults which are OpenDNS
     45 ```
     46 push "dhcp-option DNS"
     47 push "dhcp-option DNS"
     48 ```
     50 Finally reduce privileges by running as nobody, remove the comment (';') from the following lines
     51 ```
     52 user nobody
     53 group nogroup
     54 ```
     55 Save and exit your text editor.
     57 Now we need to set up the firewall. Firewall configuration on Linux is a sore subject for a lot of people, especially when trying to use the `iptables` commands. To make life easier you can opt to use a tool such as `ufw` which makes configuring the rules really easy. My guide will use the `iptables` commands because the only way to learn is by doing!
     59 Forward IPv4 traffic
     60 ```
     61 echo 1 > /proc/sys/net/ipv4/ip_forward
     62 ```
     64 Make persistant. In /etc/sysctl.conf, uncomment line
     65 ```
     66 net.ipv4.ip_forward=1
     67 ```
     69 Show iptables rules (should be blank)
     70 ```
     71 sudo iptables -L
     72 ```
     74 We are going to set up a number of rules. First we need to allow established outgoing connections. This makes life easier as we don't always know which port will be used for an outgoing connection, such as HTTP. If you prefer you can set this rule separately for each port you open, but for ease we will set it globally.
     75 The second rule is to allow incoming SSH connections. If you changed the port number used for SSH (see my Raspbian Install Guide) then you need to specify the port number.
     76 The third rule we need to set if to allow OpenVPN traffic. This port number can also be changed in the OpenVPN config file, the default is 1194.
     77 Then we need to allow TUN interface connections. We will also allow TUN connections to be forwarded through our other interface.
     78 Finally we need to NAT the OpenVPN traffic using our TUN interface. 
     79 ```
     80 sudo iptables -A OUTPUT -m conntrack --ctstate ESTABLISHED -j ACCEPT
     81 sudo iptables -A INPUT -p tcp --dport 2222 -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT
     82 sudo iptables -A INPUT -i eth0 -p udp --dport 1194 -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT
     83 sudo iptables -A INPUT -i tun+ -j ACCEPT
     84 sudo iptables -t nat -A POSTROUTING -s -o eth0 -j MASQUERADE
     85 sudo iptables -I FORWARD -i tun0 -o eth0 -s -d -m conntrack --ctstate NEW -j ACCEPT
     86 sudo iptables -A FORWARD -i tun+ -j ACCEPT
     87 sudo iptables -A FORWARD -i tun+ -o eth0 -m state --state RELATED,ESTABLISHED -j ACCEPT
     88 sudo iptables -A FORWARD -i eth0 -o tun+ -m state --state RELATED,ESTABLISHED -j ACCEPT
     89 ```
     91 Save the firewall changes in a backup file, then make the rules persistent after a reboot.
     92 ```
     93 sudo iptables-save > 20170527_iptables_rules.bak
     94 sudo invoke-rc.d iptables-persistent save
     95 ```
     97 If you ever need to apply the saved rules, if iptables is flushed for example, run the following
     98 ```
     99 sudo iptables-apply 20170527_iptables_rules.bak
    100 ```
    102 You can now run `sudo iptables -L` again to see all the rules you have entered
    103 ```
    104 Chain INPUT (policy ACCEPT)
    105 target     prot opt source               destination         
    106 ACCEPT     tcp  --  anywhere             anywhere             tcp dpt:2222 ctstate NEW,ESTABLISHED
    107 ACCEPT     udp  --  anywhere             anywhere             udp dpt:openvpn ctstate NEW,ESTABLISHED
    108 ACCEPT     all  --  anywhere             anywhere            
    110 Chain FORWARD (policy ACCEPT)
    111 target     prot opt source               destination         
    112 ACCEPT     all  --       ctstate NEW
    113 ACCEPT     all  --  anywhere             anywhere            
    114 ACCEPT     all  --  anywhere             anywhere             state RELATED,ESTABLISHED
    115 ACCEPT     all  --  anywhere             anywhere             state RELATED,ESTABLISHED
    117 Chain OUTPUT (policy ACCEPT)
    118 target     prot opt source               destination         
    119 ACCEPT     all  --  anywhere             anywhere             ctstate ESTABLISHED
    120 ```
    122 The next step is to generate the keys using `easy-rsa`. Copy the "easy-rsa" directory into our OpenVPN config directory, then create a new "keys" directory
    123 ```
    124 sudo cp -r /usr/share/easy-rsa/ /etc/openvpn/
    125 sudo mkdir /etc/openvpn/easy-rsa/keys
    126 ```
    128 Before we generate the keys we need to change the following fields in "/etc/openvpn/easy-rsa/vars"
    129 ```
    130 export KEY_COUNTRY="US"
    131 export KEY_PROVINCE="CA"
    132 export KEY_CITY="SanFrancisco"
    133 export KEY_ORG="Fort-Funston"
    134 export KEY_EMAIL="me@myhost.mydomain"
    135 export KEY_OU="MyOrganizationalUnit"
    136 export KEY_NAME="EasyRSA"
    137 ```
    138 Change the values to reflect your location and details. Also choose a name for your key (i.e. "server"), we will need this later. Save and quit your text editor
    140 Generate the Diffie-Hellman pem file, this will take a while
    141 ```
    142 sudo openssl dhparam -out /etc/openvpn/dh2048.pem 2048
    143 ```
    145 When that has finished we can generate the certificates. It is easier to do this as root as we need to source the variables. When running `build-key-server` change the server name to the one you specified in the "vars" config file
    146 ```
    147 sudo -i
    148 cd /etc/openvpn/easy-rsa
    149 source ./vars
    150 ./clean-all
    151 ./build-ca
    152 ./build-key-server server
    153 exit
    154 ```
    156 Copy the newly generated keys to your OpenVPN directory
    157 ```
    158 sudo cp /etc/openvpn/easy-rsa/keys/{server.crt,server.key,ca.crt} /etc/openvpn
    159 ```
    161 Now we can start our OpenVPN server
    162 ```
    163 sudo systemctl start openvpn
    164 sudo systemctl status openvpn
    165 ```
    167 We then have to generate keys for the clients we want on our VPN. It is good practice to have individual key pairs for each client, and not to share one key pair. This makes life easier if a device is lost or stolen, we only have to revoke one device's key pair.
    169 Generate the keys for the first client, changing the name to the device you will be using (run as root again)
    170 ```
    171 sudo -i
    172 cd /etc/openvpn/easy-rsa
    173 source ./vars
    174 ./build-key client
    175 exit
    176 ```
    178 Create a new directory to keep things tidy then copy an example client configuration file, and the keys we have just created
    179 ```
    180 mkdir ~/client
    181 sudo cp /usr/share/doc/openvpn/examples/sample-config-files/client.conf ~/client/client.ovpn
    182 sudo cp /etc/openvpn/easy-rsa/keys/{client.crt,client.key,ca.crt} ~/client
    183 ```
    185 Next open up the config file "client.ovpn". Uncomment the "nobody" and "nogroup" lines as before, also comment out the certificate and key lines
    186 ```
    187 user nobody
    188 group nogroup
    189 ;ca ca.crt
    190 ;cert client.crt
    191 ;key client.key
    192 ```
    194 Also change the line specifying the IP address of your OpenVPN server.
    195 From
    196 ```
    197 remote my-server-1 1194
    198 ```
    199 To
    200 ```
    201 remote 1194
    202 ```
    204 Replace the IP address with your network's _external_ IP address.
    206 Save and quit your text editor.
    208 Instead of copying the .ovpn file the two certs and the key across to our client, we can echo the contents of our certs into our .ovpn file and only copy the one file across to our client.
    210 The syntax for this is in XML, for example
    211 ```
    212 <tag_name>
    213 contents
    214 </tag_name>
    215 ```
    217 So we can run the following commands (as root)
    218 ```
    219 sudo -i
    220 cd /home/pyratebeard/client
    221 echo "<ca>" >> client.ovpn
    222 cat ca.crt >> client.ovpn
    223 echo "</ca>" >> client.ovpn
    224 echo "<cert>" >> client.ovpn
    225 cat client.crt >> client.ovpn
    226 echo "</cert>" >> client.ovpn
    227 echo "<key>" >> client.ovpn
    228 cat client.key >> client.ovpn
    229 echo "</key>" >> client.ovpn
    230 exit
    231 ```
    233 Securely copy the "client.ovpn" file across to your device. 
    235 For the purposes of this demonstration we are going to use a mobile phone as our device.
    237 Install and open the OpenVPN Connect app on your mobile. Import the profile file we copied across and hit connect. After a couple of seconds you should be connected to your VPN. Congrats!
    239 As mentioned at the start you will have to enable port forwarding on your router to allow traffic from outside your network into the Pi.