Chapter 7 — Commercial VPN Clients on Linux
The previous four chapters covered self-hosted VPNs — you own the server,
you control the traffic, and your public IP is your own server's IP. Commercial
VPN services flip that model: a company runs thousands of servers worldwide,
and you connect to whichever country you need. Your traffic exits from a
shared IP pool, making individual attribution harder.
This chapter covers installing and using two of the most privacy-focused
commercial providers — ProtonVPN and Mullvad
— from the Linux command line, and how to verify that neither is leaking
your real DNS queries or IP address.
ProtonVPN vs Mullvad — Key Differences
ProtonVPN
Swiss jurisdiction · open-source · free tier available
Built by the team behind ProtonMail. Strong transparency record —
published independent audits and open-sourced all clients. The free
tier is genuinely usable (no data cap, 3 countries) making it the
best free option in the market. Paid plans add Secure Core (routing
through privacy-friendly countries before exiting), NetShield
(DNS-based ad/malware blocking), and P2P servers.
- Jurisdiction: Switzerland (not EU/US)
- Logging: No-logs, independently audited
- Protocols: WireGuard, OpenVPN, Stealth (obfuscated)
- Free tier: Yes — 3 countries, unlimited data
- Linux CLI: Official
proton-vpn-gtk-app + headless mode
- Accepts: Cash, crypto, cards
Mullvad
Swedish jurisdiction · account-number only · flat €5/month
Mullvad takes anonymity further than almost any other provider:
accounts are random numbers with no email required, you can pay
in cash by post, and they have resisted and publicised law enforcement
attempts to hand over user data. The flat €5/month pricing
(no annual discounts, no tiers) keeps things simple. The Linux app
is a first-class CLI tool, not an afterthought.
- Jurisdiction: Sweden
- Logging: No-logs, independently audited
- Protocols: WireGuard, OpenVPN
- Free tier: No — €5/month flat
- Linux CLI: Official
mullvad CLI — excellent
- Accepts: Cash, Monero, Bitcoin, cards
The trust question doesn't go away. A commercial VPN
moves trust from your ISP to the VPN provider. "No-logs" claims can
only be partially verified through audits — you are ultimately trusting
the provider's honesty and jurisdiction. If true anonymity is the goal,
a VPN alone is not sufficient regardless of provider.
ProtonVPN on Linux
Install
debian/ubuntu — install ProtonVPN
# install dependencies
philip@laptop:~$ sudo apt install -y wget gnupg
# add ProtonVPN repository
philip@laptop:~$ wget -q -O- https://repo.protonvpn.com/debian/public_key.asc | \
sudo gpg --dearmor -o /usr/share/keyrings/protonvpn.gpg
philip@laptop:~$ echo "deb [signed-by=/usr/share/keyrings/protonvpn.gpg] \
https://repo.protonvpn.com/debian stable main" | \
sudo tee /etc/apt/sources.list.d/protonvpn.list
philip@laptop:~$ sudo apt update && sudo apt install -y proton-vpn-gtk-app
CLI usage (non-interactive / headless)
# login (stores credentials locally)
philip@laptop:~$ protonvpn-cli login your@email.com
# connect to the fastest available server
philip@laptop:~$ protonvpn-cli connect --fastest
Connecting to NL#47 via WireGuard...
Connected!
# connect to a specific country
philip@laptop:~$ protonvpn-cli connect --cc CH # Switzerland
philip@laptop:~$ protonvpn-cli connect --cc DE # Germany
philip@laptop:~$ protonvpn-cli connect --cc US # United States
# connect using a specific protocol
philip@laptop:~$ protonvpn-cli connect --fastest --protocol wireguard
philip@laptop:~$ protonvpn-cli connect --fastest --protocol openvpn-tcp
# show connection status
philip@laptop:~$ protonvpn-cli status
Connected to NL#47
Protocol: WireGuard
Time: 00:04:31
IP: 185.159.157.47
Country: Netherlands
Server load: 34%
# disconnect
philip@laptop:~$ protonvpn-cli disconnect
# enable kill switch (blocks internet if VPN drops)
philip@laptop:~$ protonvpn-cli killswitch --on
philip@laptop:~$ protonvpn-cli killswitch --off
Mullvad on Linux
Install
debian/ubuntu — install Mullvad
# add Mullvad repository
philip@laptop:~$ curl -fsSL https://repository.mullvad.net/deb/mullvad-keyring.asc | \
sudo gpg --dearmor -o /usr/share/keyrings/mullvad-keyring.gpg
philip@laptop:~$ echo "deb [signed-by=/usr/share/keyrings/mullvad-keyring.gpg arch=$( dpkg --print-architecture )] \
https://repository.mullvad.net/deb/stable $(lsb_release -cs) main" | \
sudo tee /etc/apt/sources.list.d/mullvad.list
philip@laptop:~$ sudo apt update && sudo apt install -y mullvad-vpn
CLI usage
# login with your account number (no email required)
philip@laptop:~$ mullvad account login 1234567890123456
Logged in to account 1234567890123456
# check account status and expiry
philip@laptop:~$ mullvad account get
Account: 1234567890123456
Expires: 2026-12-18 00:00:00 UTC
# connect (auto-selects fastest server)
philip@laptop:~$ mullvad connect
Connecting...
# show current status
philip@laptop:~$ mullvad status
Connected to Amsterdam, Netherlands (nl-ams-wg-201) via WireGuard
# set preferred country / city
philip@laptop:~$ mullvad relay set location ch # Switzerland
philip@laptop:~$ mullvad relay set location se got # Sweden, Gothenburg
philip@laptop:~$ mullvad relay set location us dal # US, Dallas
# list available countries
philip@laptop:~$ mullvad relay list | grep -E "^\w" | head -20
# set protocol
philip@laptop:~$ mullvad relay set tunnel-protocol wireguard
philip@laptop:~$ mullvad relay set tunnel-protocol openvpn
# kill switch — always on by default in Mullvad
philip@laptop:~$ mullvad lockdown-mode set on # block all traffic when disconnected
philip@laptop:~$ mullvad lockdown-mode set off
# disconnect
philip@laptop:~$ mullvad disconnect
Mullvad's lockdown mode is stricter than a standard kill
switch — it blocks all internet traffic whenever the VPN is not connected,
not just when the tunnel drops unexpectedly. This means even if you manually
disconnect, nothing gets through until you reconnect. Enable it if you want
a guarantee that unencrypted traffic is impossible on this machine.
DNS Leak Testing — Why It Matters
A DNS leak occurs when your device sends DNS queries outside the VPN
tunnel — to your ISP's resolver or your router — despite being connected
to a VPN. This reveals your browsing activity to your ISP even while the
VPN is active, defeating the purpose of using one.
DNS leaks happen because:
- The OS prefers the system DNS resolver over the VPN-pushed one
- Some browsers use their own DNS-over-HTTPS resolver (bypassing the OS)
- Split-tunnel mode may not route DNS queries through the tunnel
- IPv6 DNS resolvers leak when the VPN only tunnels IPv4
What a clean result looks like
DNS Server IP
ISP / Owner
Country
185.159.157.1
Mullvad
Netherlands
185.159.157.2
Mullvad
Netherlands
What a leaking result looks like
DNS Server IP
ISP / Owner
Country
185.159.157.1
Mullvad
Netherlands
82.132.240.1
BT (your ISP)
United Kingdom ← LEAK
DNS leak test from the terminal
linux — check DNS resolution path
# see which DNS server is currently being used
philip@laptop:~$ resolvectl status | grep "Current DNS"
Current DNS Server: 185.159.157.1 ← should be VPN provider's DNS
# quick check — query a hostname and see which server answered
philip@laptop:~$ dig +short TXT whoami.ds.akahelp.net
"ns" "185.159.157.1" ← the resolver that answered
# check for IPv6 DNS leak (if IPv6 is active)
philip@laptop:~$ dig -6 +short myip.opendns.com @2606:4700:4700::1111
# confirm no ISP DNS servers in resolv.conf
philip@laptop:~$ cat /etc/resolv.conf
nameserver 185.159.157.1 ← VPN DNS only — no leak
nameserver 185.159.157.2
Full Verification Checklist
-
🌐
Public IP check
Confirm your IP shows as the VPN server's IP, not your real IP
ipinfo.io · ifconfig.me · ipify.org
-
🔍
DNS leak test — standard
Run the standard test: all DNS servers shown should belong to the VPN provider
dnsleaktest.com → Standard Test
-
🔬
DNS leak test — extended
Runs more queries to catch intermittent leaks. Run this if the standard test passes but you're still suspicious
dnsleaktest.com → Extended Test
-
📡
WebRTC leak test
Browsers can expose your real local IP via WebRTC even through a VPN. Check that no local IPs are revealed
browserleaks.com/webrtc · ipleak.net
-
6️⃣
IPv6 leak test
If your VPN only tunnels IPv4, IPv6 traffic goes unencrypted. Mullvad and ProtonVPN block IPv6 by default when connected
ipleak.net · ipv6leak.com
-
🛡
Kill switch test
Enable kill switch, connect to VPN, then manually disconnect. Attempt to load a webpage — it should fail if the kill switch is working
curl ifconfig.me (should time out or be refused)
Browser DNS-over-HTTPS can bypass VPN DNS. Chrome and
Firefox have built-in DoH resolvers that bypass the OS DNS settings
entirely. If your VPN reports no DNS leak but the browser behaves
differently, check: Chrome → Settings → Privacy and security → Security
→ Use secure DNS — disable or point it at your VPN provider's DoH
endpoint. Firefox: about:preferences#privacy → DNS over HTTPS.
Next — Chapter 8: Troubleshooting and Security Hardening.
The final chapter covers DNS leaks in depth, kill switch implementation,
MTU issues (the silent performance killer), logging and audit, and a
practical checklist for verifying that your VPN setup — self-hosted or
commercial — is actually doing what you think it is.