20170718-raspberry_pi_vpn.md (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. 2 3 For this guide I will be continuing on with the basic install as it was after the previous post. 4 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 [whatismyip.com](https://whatismyip.com). 6 7 ## Open(VPN) your world 8 9 There are a number of VPN server options out there, but the most popular is [OpenVPN](https://openvpn.net/). 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. 10 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 ``` 17 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 ``` 23 24 Open the config file for editing 25 ``` 26 sudo vi /etc/openvpn/server.conf 27 ``` 28 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 ``` 38 39 Remove comment (';') from the DHCP redirect line 40 ``` 41 push "redirect-gateway def1 bypass-dhcp" 42 ``` 43 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 208.67.222.222" 47 push "dhcp-option DNS 208.67.220.220" 48 ``` 49 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. 56 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! 58 59 Forward IPv4 traffic 60 ``` 61 echo 1 > /proc/sys/net/ipv4/ip_forward 62 ``` 63 64 Make persistant. In /etc/sysctl.conf, uncomment line 65 ``` 66 net.ipv4.ip_forward=1 67 ``` 68 69 Show iptables rules (should be blank) 70 ``` 71 sudo iptables -L 72 ``` 73 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 10.8.0.0/24 -o eth0 -j MASQUERADE 85 sudo iptables -I FORWARD -i tun0 -o eth0 -s 10.8.0.0/24 -d 192.168.0.0/24 -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 ``` 90 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 ``` 96 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 ``` 101 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 109 110 Chain FORWARD (policy ACCEPT) 111 target prot opt source destination 112 ACCEPT all -- 10.8.0.0/24 192.168.0.0/24 ctstate NEW 113 ACCEPT all -- anywhere anywhere 114 ACCEPT all -- anywhere anywhere state RELATED,ESTABLISHED 115 ACCEPT all -- anywhere anywhere state RELATED,ESTABLISHED 116 117 Chain OUTPUT (policy ACCEPT) 118 target prot opt source destination 119 ACCEPT all -- anywhere anywhere ctstate ESTABLISHED 120 ``` 121 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 ``` 127 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 139 140 Generate the Diffie-Hellman pem file, this will take a while 141 ``` 142 sudo openssl dhparam -out /etc/openvpn/dh2048.pem 2048 143 ``` 144 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 ``` 155 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 ``` 160 161 Now we can start our OpenVPN server 162 ``` 163 sudo systemctl start openvpn 164 sudo systemctl status openvpn 165 ``` 166 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. 168 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 ``` 177 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 ``` 184 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 ``` 193 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 192.30.252.153 1194 202 ``` 203 204 Replace the IP address with your network's _external_ IP address. 205 206 Save and quit your text editor. 207 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. 209 210 The syntax for this is in XML, for example 211 ``` 212 <tag_name> 213 contents 214 </tag_name> 215 ``` 216 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 ``` 232 233 Securely copy the "client.ovpn" file across to your device. 234 235 For the purposes of this demonstration we are going to use a mobile phone as our device. 236 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! 238 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. 240