Virtual private networks
More options for internet privacy
2017-04-15 — 2026-05-20
Wherein the Distinction Between Anonymous Access and Private Mesh Networking Is Drawn, the DNS Leakage Attendant Upon OpenVPN Under Linux Is Described, and Methods of Split Tunneling by Platform Are Surveyed.
VPN stands for Virtual Private Network. There are two main things I might want to do with such a thing:
- Connect a bunch of my devices together in a distributed network which is also a private intranet (secure access)
- Connect my devices together with some total strangers’ devices so that when some adversary monitors my internet traffic it is hard to work out what traffic is mine and what is the total strangers’. (anonymous access)
The priorities for both are different. I mostly assume option (2) in this, although I am interested in (1) for DIY socials, backup and private clouds, so I made a notebook for that called virtual meshnets.
For this purpose, the EFF recommends Americans get a VPN. This applies also in my jurisdiction, Australia. Probably it’s time everywhere, except places like China where it may be too late.
VPNs do of course degrade internet bandwidth, but Australians are used to awful internet anyway, so this is not a major issue for me.
OK, so I need a VPN to maintain privacy. How? Server-wise, do I want to DIY, or pay someone else to provide it? Which VPN software should I use?
(Or should we bypass the internet with a sneakernet or DIY internet? That’s another story.)
There are related technologies here that do similar things. OpenVPN, IPSec, Wireguard… The fashionable new one is Wireguard, though there are questions about how anonymous it is in commercial VPN provider environments.
1 Client-side configuration
My devices, using the internet.
Now I want to install the right client software; this should be straightforward but of course it is not. Just get an account with some VPN provider, and follow their instructions.
This works great for my phone or laptop in some arbitrary café hotspot, but it is not ideal for my home devices on the home intranet. See below for VPN access points.
Having set up the VPN there may still be data leakages by default. Vpn.ac has a nice basic list of basic privacy steps disabling unsafe behaviour from the web browser end etc, and one should still enable the usual browser safety steps. Notes for particular platforms follow:
1.1 Linux
So you followed the recommended setup for your VPN provider. Good.
Gotcha: OpenVPN is broken for DNS on Linux by default, in the sense that switching to a VPN connection keeps the same old DNS servers that you were using before. In the absence of further effort, OpenVPN on Linux will use your ISP’s DNS, informing them which site you want and will believe their potentially lying responses. This seems to defeat the purpose.
I think this is not a pure Linux problem per se but because VPN providers tend to provide wrapper scripts for macOS and Windows, one only notices this monstrous oversight on Linux where you are going bareback. Not 100% sure on that, don’t care quite enough to find out.
Lazy detection of this problem is possible via DNSLeaktest.
The Linux fix requires telling OpenVPN to update the system resolver when the tunnel comes up. With the resolvconf package installed, adding these lines to the .ovpn config does it:
On systemd-resolved systems (most current Ubuntu/Debian), use jonathanio/update-systemd-resolved instead—it integrates with systemd-resolved via DBus rather than altering /etc/resolv.conf directly. Using a VPN client that handles this automatically—Mullvad’s client does—sidesteps the whole thing.
One can always use the DNS config to override the DNS to never use your ISP’s DNS, which you probably should do. On GNOME/Ubuntu using a large VPN provider with hundreds of servers, the default way of doing this will be messy and require hundreds of custom DNS configurations, which is no fun at all. 🏗 workaround.
Another problem is that VPNs occasionally disconnect and then I’m not protected and don’t notice.
Auto-reconnect is not available in e.g. modern GNOME desktops, but you can access this setting using the command:
To make sure my computer does not leak information during a VPN disconnect, perhaps vpnfailsafe would be a good idea, or other iptables-based hardening.
1.2 macOS
The basic setup is straightforward: install the client from whichever provider we’re using, authenticate, connect. The DNS leak problem that plagues Linux OpenVPN doesn’t generally surface on macOS because provider clients handle resolver configuration themselves.
For granular control over which traffic goes through the tunnel, see split tunneling below.
2 Split tunneling
The basic VPN setup is all-or-nothing: either everything goes through the tunnel or nothing does. This turns out to be wrong in two different directions at once.
Some services refuse connections from shared VPN exit nodes—the IP ranges that commercial VPN providers use get associated with spam runs, and the blocks are applied to the whole range rather than individual offenders. At the same time, some services are only reachable through a VPN exit—Indonesia’s content-filtering regime, for instance, casts a wide net, and various servers end up miscategorised in it. Any uniform configuration is therefore wrong for at least some traffic.
Split tunneling is the general name for routing some traffic through the VPN and some around it—by app, by destination IP range, by domain, or some combination. The mechanics vary by platform and by how granular we want to be.
- Per-subnet routing is the oldest approach: manually add routes so traffic destined for specific IP ranges exits through the tunnel (or bypasses it). Works everywhere, requires knowing the relevant IP ranges, and breaks when they change.
- Per-app routing is available through some VPN clients on Windows, Linux, and now macOS—we nominate which applications bypass the tunnel. Coarser than per-domain, but zero ongoing maintenance.
- Per-domain routing requires a proxy layer sitting in front of DNS—matching outbound requests against a ruleset before deciding which exit to use. Most powerful, most complex to set up.
- Per-browser routing is a practical middle ground: Firefox maintains its own proxy settings, independent of the OS, so we can point it at a different exit than the rest of the system with no special tooling.
2.1 Linux
Linux is better-placed than macOS for split tunneling—the kernel gives us enough rope. I haven’t tested these myself, but the options that come up repeatedly are:
Subnet routing is the simplest case and works with any VPN protocol. Add route-nopull to the OpenVPN config to stop the server from overriding routes, then add explicit routes for whatever subnets should go through the tunnel. WireGuard handles this more cleanly via the AllowedIPs field in the peer config—set it to specific subnets rather than 0.0.0.0/0 and only matching traffic enters the tunnel.
Network namespaces are the Linux-native approach for per-app split tunneling. The idea is to create an isolated network namespace containing the VPN interface, then run specific applications inside it with ip netns exec. Everything outside the namespace uses the regular connection; everything inside goes through the VPN. This walkthrough using WireGuard and namespaces covers the mechanics in detail, and Pro Custodibus has a thorough treatment of the same pattern. Lower-level than anything available on macOS, but the setup is fiddly and there’s no GUI.
VPN client split tunneling is available if we’re using Mullvad or PIA on Linux—both support per-app exclusion via their native clients without needing to touch namespaces manually.
2.2 macOS
Apple’s network extension APIs, introduced in Big Sur, constrain what third-party apps can do with routing—and many providers haven’t implemented split tunneling on Mac as a result. NordVPN still doesn’t support it as of 2025. The options below are in order of increasing setup cost.
2.2.1 VPN clients with built-in split tunnelling
Mullvad added per-app split tunnelling to their macOS client in version 2024.4, stabilising it in early 2025. The logic is inverse: we specify apps to exclude from the VPN tunnel, and everything else goes through it. That’s the right default for my purposes—I want the VPN by default, with specific apps or browsers exempted.
Setup is in the Mullvad app under Settings → Split Tunnelling. Add whichever apps should bypass the tunnel. Requires macOS 13 (Ventura) or newer.
The limitations: no per-domain control (it’s per-app only), and Mullvad has had occasional compatibility issues with Little Snitch. More to the point, this requires switching VPN providers if we’re currently on one that doesn’t support it. Surfshark’s Bypasser is the other commonly recommended option and supports per-domain rules in addition to per-app.
2.2.2 Firefox with a SOCKS5 tunnel
Firefox maintains its own network settings, independent of the macOS system proxy. This means we can route the browser through a different exit than the rest of the machine—which is precisely the per-application split we want, for the browser at least.
We need a SOCKS5 endpoint. The simplest: an SSH tunnel to any server we have shell access to.
This opens a local SOCKS5 proxy on port 1080, tunnelling outbound through that server. Then in Firefox: Settings → General → Network Settings → Manual proxy configuration. Set SOCKS Host to 127.0.0.1, port 1080, SOCKS v5. Tick “Proxy DNS when using SOCKS5”—otherwise DNS queries still go through the system path and we get a DNS leak.
The upshot: Firefox exits through the SSH server, everything else exits through the VPN (or directly). We can invert this as well—run the VPN system-wide and give Firefox a direct route by pointing it at a transparent local proxy. Chrome can’t do this because it delegates to macOS system proxy settings; Firefox keeps its own. For per-domain switching within the browser, FoxyProxy is worth knowing about.
2.2.3 Routing table surgery
For subnet-level control—routing traffic to specific IP ranges through or around the VPN—the macOS route command still works.
The VPN gateway IP shows up in netstat -nr once the tunnel is up; look for the gateway on the utun interface. This walkthrough covers the mechanics in more detail, including how to automate route setup on VPN connect via a script.
The limitations are significant: routes are ephemeral (cleared on VPN disconnect or reboot), and this only works at the IP/subnet level—no per-domain, no per-app. For corporate access scenarios (“send traffic to the office subnet through the tunnel, everything else direct”) this is enough. For consumer VPN scenarios involving content-filtering regimes or IP-reputation blocks, it’s impractical—we’d need to enumerate all the relevant IP ranges and keep them current.
For per-domain or per-process routing with full flexibility, Clash Verge Rev is the most capable free option currently available. It’s a rule-based proxy router that can run in TUN mode—intercepting system traffic through a virtual network interface and applying routing rules before anything hits the wire. Rules can match on domain, IP range, or process name. The setup cost is non-trivial: it requires a proxy endpoint (WireGuard, Shadowsocks, or similar) and familiarity with Mihomo/Clash rule syntax. TUN mode has had stability issues on macOS in 2025, though the project is actively maintained. Worth keeping in reserve if the simpler approaches don’t cover the need.
3 VPN access points
By default, our household devices should not have to route communications between one another via Amsterdam. This is terrible for sharing files from the network file server, copying photos, or streaming from the household media server. Instead, our network should be a normal WiFi network, but the wire that connects us to the outside world—everything that goes over that wire—should be encrypted. This is possible. See VPN Access Points.
Alternatively, one can configure devices to bypass the VPN for local network connections; this is surprisingly fiddly.
4 Server end
That which provides our devices this service of confidentiality.
Note that server virtual machines on someone else’s cloud can never be especially secure from determined adversaries or state actors. But they do at least prevent concerted profiling by commercial interests, and casual ambient profiling by the state, which is good enough for me.
A commercial VPN provider can do better, if their intentions are pure, since they can hide your traffic amongst the traffic of many others. On the other hand, a commercial VPN might be selling your data to evil bastards for their own profit, so… make your own risk assessment.
4.1 Commercial VPN services
BlackVPN, which I used to mention here, has shut down. The three providers I have some familiarity with are below. For a broader comparison by jurisdiction, no-logs policy, and protocol support, privacyguides.org maintains a reasonably current overview.
4.1.1 Mullvad
Mullvad is the privacy-first option. They accept cash and Monero, assign account numbers rather than email addresses, have published detailed explanations of what they do and don’t log, and have had their no-logs claims verified by independent audit. The client is open-source. On macOS it now supports per-app split tunnelling (as of 2024–2025) and also operates a meshnet service. The trade-off is that it’s more expensive than the marketing-heavy providers and has fewer servers.
4.1.2 Surfshark
Surfshark is the feature-rich option. It supports per-app and per-domain split tunnelling on macOS (branded as Bypasser), which is unusual—most providers still don’t. Cheaper than Mullvad on multi-year plans. It’s considerably more commercial in orientation than Mullvad; make the usual risk assessment about whether their business model is compatible with their privacy claims.
4.1.3 NordVPN
Classic large-scale commercial VPN. Fast, cheap, wide server coverage. Their record with disclosing security breaches could be better. They also operate a meshnet service, and the client is available for Linux:
Some installs need the services enabled manually:
The client is closed-source. It does not support split tunnelling on macOS.
4.2 DIY OpenVPN server
Running your own VPN/proxy/anonymising/p2p etc. servers can be less convenient for the panopticon in its ceaseless attempts to get up in your business, if you don’t trust the VPN providers (but, if it’s hosted in a cloud, you do trust the cloud providers.) The tradeoff here is that you want to share a VPN server with other people so that you are collectively anonymised. If it is just me always using the same VPN server then it is not hard to de-anonymise me; I’m the guy who is always using that server. Once again, make your own risk assessment here.
- Easy with simple GUI, outline
- somewhat-secure, cheap, light VPN in the cloud: popup-openvpn.
- streisand
- openvpn on docker+digitalocean: See kylemanna/openvpn, and the digitalocean pitch, or the alternative walkthrough with a couple more terms clarified.
Even easier than a real VPN, try turning your SSH login into a quasi-VPN via sshuttle.
5 Stealth mode
Hiding that we are hiding. A regular OpenVPN or WireGuard handshake is recognisable to deep packet inspection, so jurisdictions that block VPN traffic (notably China, also Iran and Russia at times) can drop the connection on sight. The countermeasure is to dress the tunnel up as something innocuous—typically TLS-over-HTTPS.
The older Tor approach uses obfsproxy and other pluggable transports. These work, so I am told, but the setup is laborious.
The currently-dominant family for circumventing the Great Firewall is the Shadowsocks lineage—a SOCKS5-shaped protocol with traffic obfuscation, plus its descendants V2Ray/VMess, VLESS, Trojan, and Hysteria2. These are what Shadowrocket (iOS) and Clash Verge Rev (desktop, mentioned above) actually speak. See China for the specific Great-Firewall context where these matter most.
Pre-rolled scripts from sites such as scramblevpn walk through turning a cheap Raspberry Pi into a router that does some of this for us.
6 Tor
Is already its own proxy/privacy thingy. If you are using a computer on Tor you should not use a VPN through Tor. If you want to hide that you are using Tor, you could use Tor through a VPN.
7 Other
How does tcpcrypt fit in?
tcpcrypt is a protocol that attempts to encrypt (almost) all of your network traffic. Unlike other security mechanisms, Tcpcrypt works out of the box: it requires no configuration, no changes to applications, and your network connections will continue to work even if the remote end does not support Tcpcrypt, in which case connections will gracefully fall back to standard clear-text TCP. Install Tcpcrypt and you’ll feel no difference in your everyday user experience, but yet your traffic will be more secure and you’ll have made life much harder for hackers.
- BeyondCorp Zero Trust Enterprise Security does without VPN entirely, getting devices to… what? Authenticate piecemeal?
