How to properly set up PIA VPN on a Raspberry Pi with a killswitch
Intro
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:
- Pi VPN Setup for PIA with killswitch and DHCP - Does not work
- OpenVPN systemd use
Setup
The usual...
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.
curl https://ipleak.net/json/
Install OpenVPN on your Raspberry
sudo apt install openvpn -y
Create a
login
file for OpenVPN. Since PIA VPN usesauth-pass
in 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 failure
on 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
ping
went 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 exampleus-california.conf
as this filename will become the name of the OpenVPN service later. Modify the file you just created (I suggestnano
) 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
systemctl
magic comes in.sudo systemctl start openvpn-client@<country>
So based on the above example,
<country>
isus-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.
curl https://ipleak.net/json/
You can stop and start the OpenVPN service with replacing
start
withstop
or get information about the service withstatus
.Enable the service so it starts at boot. We want the connection to automatically get established after each reboot. When you
enable
a service with systemctl, it will run at boot if the server gets restarted. Replacecountry
as above.sudo systemctl enable openvpn-client@<country>
Reboot with
sudo reboot
. After the server has started again, SSH in and test if your connection is up with the same commandcurl https://ipleak.net/json/
. Take note of the IP address and make sure you are indeed connecting through your new VPN tunnel.Set up
iptables
rules. 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
udp:53
andtcp:502
as discussed above. If you are using a different configuration than the recommended TCP one, make sure to change these commands accordingly. Changetcp
toudp
and502
to1198
.Make sure to change the
192.168.0.0
to your local network's address, while keeping the/24
CIDR.# 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
iptables
but 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 commandcurl 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 tostart
theopenvpn-client@<country>
service.Install
iptables-persistent
so the configuration persists even after a reboot. When asked if you'd like to save the current configuration, clickyes
. 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>