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.
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.
# login (stores credentials locally)philip@laptop:~$protonvpn-cli login your@email.com# connect to the fastest available serverphilip@laptop:~$protonvpn-cli connect --fastestConnecting to NL#47 via WireGuard...Connected!# connect to a specific countryphilip@laptop:~$protonvpn-cli connect --cc CH# Switzerlandphilip@laptop:~$protonvpn-cli connect --cc DE# Germanyphilip@laptop:~$protonvpn-cli connect --cc US# United States# connect using a specific protocolphilip@laptop:~$protonvpn-cli connect --fastest --protocol wireguardphilip@laptop:~$protonvpn-cli connect --fastest --protocol openvpn-tcp# show connection statusphilip@laptop:~$protonvpn-cli statusConnected to NL#47
Protocol: WireGuard
Time: 00:04:31
IP: 185.159.157.47
Country: Netherlands
Server load: 34%# disconnectphilip@laptop:~$protonvpn-cli disconnect# enable kill switch (blocks internet if VPN drops)philip@laptop:~$protonvpn-cli killswitch --onphilip@laptop:~$protonvpn-cli killswitch --off
# login with your account number (no email required)philip@laptop:~$mullvad account login 1234567890123456Logged in to account 1234567890123456# check account status and expiryphilip@laptop:~$mullvad account getAccount: 1234567890123456
Expires: 2026-12-18 00:00:00 UTC# connect (auto-selects fastest server)philip@laptop:~$mullvad connectConnecting...# show current statusphilip@laptop:~$mullvad statusConnected to Amsterdam, Netherlands (nl-ams-wg-201) via WireGuard# set preferred country / cityphilip@laptop:~$mullvad relay set location ch# Switzerlandphilip@laptop:~$mullvad relay set location se got# Sweden, Gothenburgphilip@laptop:~$mullvad relay set location us dal# US, Dallas# list available countriesphilip@laptop:~$mullvad relay list | grep -E "^\w" | head -20# set protocolphilip@laptop:~$mullvad relay set tunnel-protocol wireguardphilip@laptop:~$mullvad relay set tunnel-protocol openvpn# kill switch — always on by default in Mullvadphilip@laptop:~$mullvad lockdown-mode set on# block all traffic when disconnectedphilip@laptop:~$mullvad lockdown-mode set off# disconnectphilip@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
dnsleaktest.com — Extended Test results✓ No leak detected
DNS Server IP
ISP / Owner
Country
185.159.157.1
Mullvad
Netherlands
185.159.157.2
Mullvad
Netherlands
What a leaking result looks like
dnsleaktest.com — Extended Test results✗ Leak detected — your ISP can see your queries
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 usedphilip@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 answeredphilip@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.confphilip@laptop:~$cat /etc/resolv.confnameserver 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.