~/blog/protonvpn-on-linux
Published on

Setting up ProtonVPN on Linux

620 words4 min read
Authors
  • avatar

Pre-requisites

  1. Install openresolv - apt install openresolv
  2. Install iptables - apt install iptables

Create a Wireguard configuration file

  1. Install the official WireGuard VPN CLI tool for your distribution
  2. Sign in to account.protonvpn.com, go to Downloads → WireGuard configuration, and download a WireGuard configuration file.
  3. Download and copy the contents of the new configuration file to your Linux box to the /etc/wireguard directory (e.g. /etc/wireguard/test-UK-001)
  4. Confirm it works by running sudo wg-quick up $configName (e.g. sudo wg-quick up test-UK-001) and then running sudo wg
  5. Optionally confirm the VPN is running by checking the IP returned by wget -qO- icanhazip.com is not your assigned IP address.
  6. End the session by running sudo wg-quick down $configName (e.g. sudo wg-quick down test-UK-001).

Enable and run the Wireguard configuration via systemd

This step ensures that the Wireguard configuration automatically starts on boot

  1. Run sudo systemctl enable --now wg-quick@$configName to create the system service, enable it, and start it immediately (e.g. sudo systemctl enable --now wg-quick@test-UK-001)
  2. Confirm the service is running with sudo systemctl status wg-quick@$configName (e.g. sudo systemctl status wg-quick@test-UK-001`)

Set-up a kill switch

This step uses Wireguards postup and predown options to prevent traffic if the VPN interface goes down.

  1. Edit your confiration under /etc/wireguard and add the following under the [Interface] section. Note: The ! -d 192.168.1.0/24 argument excludes the subnet range from the rule, allowing you to still SSH etc. Change this to suit your subnet as appropriate.
PostUp = iptables -I OUTPUT ! -o %i -m mark ! --mark $(wg show %i fwmark) -m addrtype ! --dst-type LOCAL ! -d 192.168.1.0/24 -j REJECT && ip6tables -I OUTPUT ! -o %i -m mark ! --mark $(wg show %i fwmark) -m addrtype ! --dst-type LOCAL -j REJECT
PreDown = iptables -D OUTPUT ! -o %i -m mark ! --mark $(wg show %i fwmark) -m addrtype ! --dst-type LOCAL ! -d 192.168.1.0/24 -j REJECT && ip6tables -D OUTPUT ! -o %i -m mark ! --mark $(wg show %i fwmark) -m addrtype ! --dst-type LOCAL -j REJECT

For example:

[Interface]
PrivateKey = abcdefghijklmnopqrstuvwxyz0123456789=
Address = 172.x.y.z/32
DNS = 172.16.0.1
PostUp = iptables -I OUTPUT ! -o %i -m mark ! --mark $(wg show %i fwmark) -m addrtype ! --dst-type LOCAL ! -d 192.168.1.0/24 -j REJECT && ip6tables -I OUTPUT ! -o %i -m mark ! --mark $(wg show %i fwmark) -m addrtype ! --dst-type LOCAL -j REJECT
PreDown = iptables -D OUTPUT ! -o %i -m mark ! --mark $(wg show %i fwmark) -m addrtype ! --dst-type LOCAL ! -d 192.168.1.0/24 -j REJECT && ip6tables -D OUTPUT ! -o %i -m mark ! --mark $(wg show %i fwmark) -m addrtype ! --dst-type LOCAL -j REJECT


[Peer]
PublicKey = JPT1veXLmasj2uQDstX24mpR7VWD+GmV8JDkidkz91Q=
Endpoint = us-tx1.wg.ivpn.net:2049
AllowedIPs = 0.0.0.0/0
  1. Restart the service with sudo systemctl restart wg-quick@$configName
  2. Confirm the iptables rules have been applied with iptables -L