Two VPN clients can run side by side, but their kill switches do not merge into one policy. Each client installs rules for its own tunnel, and neither one knows the other exists. I hit this with a work client connected first: the second app could not finish its handshake, sat on “Connecting” for ten minutes, and the first tunnel quietly carried everything. Whether the second app gets protected comes down to three conditions, not to whether both icons say Connected.

What a kill switch is actually scoped to

Nothing in the operating system has a single kill-switch flag. A client that advertises one installs a rule set: drop everything that does not leave through my tunnel, and often fail closed when the tunnel goes away. On Linux that is usually an nftables or iptables chain, on Windows a set of Windows Filtering Platform filters, on Android and iOS the tunnel service’s own routing plus the system setting that blocks connections without VPN. The Android VPN guide describes that service model if you want the platform view.

The scope is the part that matters. A rule such as allow only packets on output interface wg0 does not care whether a second tunnel exists. If another client brings up wg1, the first client’s rules treat those packets as ordinary traffic: usually dropped, occasionally allowed. Either way the first client is deciding, and it has no idea a second app is waiting.

Three conditions that decide who gets covered

You do not need to enumerate every combination. Three questions settle it in a few minutes.

  1. Does the platform allow a second tunnel at all? Most Android phones and iPhones accept only one active VPN service per user profile, so the second app never holds a tunnel and never enforces anything. You get one policy, from the app that won the slot.
  2. Which process owns the default route? Windows, macOS and Linux will happily carry two tunnels. The default route belongs to whichever client configured it last or with the better metric, and the other client is connected but idle. On Linux, wg-quick’s default-route mode uses policy routing with a private table and an fwmark rule, so a second wg-quick tunnel adds a competing rule instead of replacing the first.
  3. Can the second client reach its own server? If the first kill switch is default-deny, the second app’s outer endpoint is just another dropped destination. It retries silently and never reports an error.

The short version, for support threads:

SetupWhat you actually get
Second client cannot hold a tunnelOne active policy; the other app only reports that it is waiting
Both tunnels up, second took the default routeThe first kill switch blocks traffic it never meant to touch; the connection dies, or leaks if its rules are broad
First kill switch allows only its own endpoint and interfaceSecond client never connects; first tunnel unaffected
Both up, DNS written by whichever client ran lastName resolution breaks for one side when either tunnel drops

Two of those rows look identical from the tray icon, which is why the icon is the worst evidence available here.

What fails first, and how it looks

A client stuck on Connecting while the other is healthy is almost always endpoint starvation: the running kill switch drops the second client’s handshake to its own server. Confirm it cheaply by pausing the first client’s block rules for one attempt. If the second connects immediately, the question is answered.

DNS is the second failure. Clients set resolver configuration for their own interface, and some overwrite the global resolver list outright. With both tunnels up, queries can leave through one side while the resolver belongs to the other. Disconnect either app and the survivor keeps an unreachable nameserver: pages stall for a minute and then resolve again, while the VPN still shows connected.

The third is route flapping. Reconnects reorder the default route, and an interface-bound kill switch does not follow it. Traffic that was inside the tunnel a moment ago now matches a drop rule, which reads on the user side as a VPN that randomly stops working.

Verify which policy is actually in force

Run this with harmless traffic, not with something you would miss.

On Linux, ask the kernel who wins and what the firewall binds to. ip -4 route show default names the tunnel that owns egress. ip rule show shows whether policy routing is in play. sudo nft list ruleset | grep -n oifname shows whether drops are bound to an interface name, a mark, or the whole output chain.

On Windows the same story lives in the route metric and the filter list: Get-NetRoute -DestinationPrefix "0.0.0.0/0" | Sort-Object RouteMetric and Get-NetFirewallRule -Enabled True | Where-Object DisplayName -match "VPN". On macOS, netstat -rn -f inet | head -5 and scutil --dns | head -20.

Then do the step people skip: stop the tunnel on purpose and confirm that the traffic you expect to fail really fails. A connected icon is a UI state, not enforcement.

When two clients is the wrong design

If the only requirement behind the second app is more protection, remove it. Two interacting block policies are less predictable than one, and every reconnect is a chance to land in a state neither vendor tests.

If you genuinely need chaining, such as a corporate gateway reached over a commercial hop, pick a design with one enforcement point. That normally means a router or a single client that supports the chain, not two desktop apps racing for the same default route. On a managed device, keep the sanctioned client and treat anything else as out of scope, whatever it shows in its tray.

Checklist before you keep both

Work down this list in order; the first item that fails is the one to fix.

  • Confirm exactly one client owns the default route and the resolver.
  • If you want the second client up, allow its server endpoint explicitly and re-check after every client update.
  • Write down the expected outcome when either tunnel drops, then test that specific case.
  • Check the failure path after a reboot, when start order is different.
  • On a managed profile, stop and ask the owner before adding anything.

If step three fails, the honest answer is that only one client is giving you a policy. Decide which one you trust and let the other go.

Inyandiko zihuye