How to properly set up PIA VPN on a Raspberry Pi with a killswitch
This post was written on the 14th of November 2020. I feel the need to start with that because all of the guides out there on the internet are too old and do not work anymore. I never liked dealing with OpenVPN, let alone on a Raspberry Pi but here we are. I needed this setup because I want to turn one of my Raspberry Pis into a seedbox, and I sleep much better at night when it's behind a VPN. My personal choice is PIA. I'd have a hard guess that this setup / method works with anything that uses OpenVPN however. Mine runs the latest (as of November 2020) Raspberry Pi OS on a Raspberry Pi 3, but it will work on the 4 as well. We will be running PIA via OpenVPN fully in headless mode.
I took help from the following articles:
sudo apt update && sudo apt upgrade -y
Check if you have an internet connection to begin with. Take note of the IP address displayed there, that's your current public IP without the VPN.
Install OpenVPN on your Raspberry
sudo apt install openvpn -y
loginfile for OpenVPN. Since PIA VPN uses
auth-passin its configuration, we need to save the PIA username + password in a file on the server - the same you use to log into the desktop app or website. While this is not technically "best practice", I could not come up with a safer way. As long as your Pi is well secured, it should not be a problem.
sudo bash -c 'echo "USERNAME" >> /etc/openvpn/login' sudo bash -c 'echo "PASSWORD" >> /etc/openvpn/login'
Download PIA OpenVPN config file. Go to PIA OpenVPN Configurator and create a configuration file for your favorite location. Couple very important things here:
- I got
access denied - authentication failureon some of the servers, the others worked perfectly. Try another server if you face this issue as well.
- You can only have a single location at a time. There is no automatic failover or connection to another region. Make sure to choose one that is reliable 24/7. For me for example, the closest server is always very busy with high latency throughout the evening, so I chose one that's a bit further but never as congested. Your speed should not be affected that much anyways as long as it's decently close.
- Use the Recommended TCP configuration. When I tried with the recommended UDP configuration files, there was a successful connection and
pingwent through as well, but nothing else. I had a connection on paper, but there was no data flow. I don't know why this happened, but switching to the TCP/:502 setup solved the problem instantly.
- I got
Save your configuration with
nano /etc/openvpn/client/<country>.conf. Name it something simple, for example
us-california.confas this filename will become the name of the OpenVPN service later. Modify the file you just created (I suggest
nano) at the following line:
auth-user-pass -> auth-user-pass /etc/openvpn/login. If you do not do this, OpenVPN will ask for a username and password each time you want to connect, and that's not a good headless setup.
Try the connection, this is where the new
systemctlmagic comes in.
sudo systemctl start openvpn-client@<country>
So based on the above example,
us-californa. This should give you a some nice lines signaling that you are connected to the VPN.
Type the following command, this will give you information about your connection. It will show you your current public IP address and you'll compare that to the one from before. If they match, your VPN is not working correctly. The goal is for them not to match of course.
You can stop and start the OpenVPN service with replacing
stopor get information about the service with
Enable the service so it starts at boot. We want the connection to automatically get established after each reboot. When you
enablea service with systemctl, it will run at boot if the server gets restarted. Replace
sudo systemctl enable openvpn-client@<country>
sudo reboot. After the server has started again, SSH in and test if your connection is up with the same command
curl https://ipleak.net/json/. Take note of the IP address and make sure you are indeed connecting through your new VPN tunnel.
iptablesrules. This is where we'll set up that all packets - directed outside of your local network - get dropped that are not going through the VPN tunnel. Execute these commands together otherwise you will be locked out of your server before you can finish. Copy the whole thing and paste as one.
This allows in/output through port
tcp:502as discussed above. If you are using a different configuration than the recommended TCP one, make sure to change these commands accordingly. Change
Make sure to change the
192.168.0.0to your local network's address, while keeping the
# Allow loopback device (internal communication) sudo iptables -A INPUT -i lo -j ACCEPT sudo iptables -A OUTPUT -o lo -j ACCEPT #Allow all local traffic. sudo iptables -A INPUT -s 192.168.0.0/24 -j ACCEPT sudo iptables -A OUTPUT -d 192.168.0.0/24 -j ACCEPT # Allow VPN establishment # Only 2 ports open, 1 for DNS and 1 for VPN # If establishing thru an IP and not a name, the ones with port 53 can be removed # Port 1198 may be different depending on the VPN sudo iptables -A OUTPUT -p udp --dport 53 -j ACCEPT sudo iptables -A INPUT -p udp --sport 53 -j ACCEPT sudo iptables -A OUTPUT -p tcp --dport 502 -j ACCEPT sudo iptables -A INPUT -p tcp --sport 502 -j ACCEPT #Accept all TUN connections (tun = VPN tunnel) sudo iptables -A OUTPUT -o tun+ -j ACCEPT sudo iptables -A INPUT -i tun+ -j ACCEPT #Set default policies to drop all communication unless specifically allowed sudo iptables -P INPUT DROP sudo iptables -P OUTPUT DROP sudo iptables -P FORWARD DROP
As I said I'm not a pro in
iptablesbut these commands work well, just make sure if you modify any of it not to execute something you don't fully understand. If you are still connected, execute the command
curl https://ipleak.net/json/to check if you still have a connection to the internet and it is still going through the VPN tunnel. If it doesn't work, make sure to
iptables-persistentso the configuration persists even after a reboot. When asked if you'd like to save the current configuration, click
yes. The server will restart automatically, SSH in again when it comes back up.
sudo apt-get install iptables-persistent -y && sudo netfilter-persistent save && sudo systemctl enable netfilter-persistent && sudo reboot
Test if the killswitch is still working. With the following commands you can start & stop the OpenVPN service, as well as get the current status of it. You can execute the usual
curl https://ipleak.net/json/to test your connection. Remember, when the OpenVPN service is not running, you must not have any kind of internet connection.
sudo systemctl start openvpn-client@<country> sudo systemctl stop openvpn-client@<country> sudo systemctl status openvpn-client@<country>