How a VPN Kill Switch Fails Closed, and Where It Doesn't
A kill switch is not a switch and it does not kill anything. It is a set of packet-filtering rules that permit outbound traffic on the tunnel’s virtual interface and refuse it everywhere else, so that if the tunnel stops carrying packets your traffic has nowhere else to go and simply fails. That behaviour is what “fail closed” means: when the protection breaks, the thing being protected stops rather than continuing unprotected.
Understanding it as a firewall rule rather than a feature toggle explains both why it works and the specific moments when it does not.
Fail closed, described at the level it operates
Three pieces of your networking stack are involved, and the rules have to agree with all of them.
The interface. When a client connects, it creates a virtual network interface representing the tunnel. Packets handed to that interface get encapsulated and sent to the VPN server. When the tunnel stops, the interface either disappears or stays present while going nowhere.
The routing table. Your device picks an interface per packet by matching the destination against its routes, and a connected client normally installs a default route pointing at the tunnel. If the interface vanishes, its routes go with it and your original default route through the local network becomes the best match again. That reversion is the leak: nothing failed loudly, the traffic just took the older path.
The packet filter. This is where the kill switch lives, as a narrow allow-list: permit outbound packets on the tunnel interface, permit packets to the VPN server’s own address on the tunnel’s port — otherwise the client could never reconnect — and block the rest. Usually there is also an exception for your local subnet, which is itself a small opening.
With those rules in place, the routing reversion still happens, but the packets that follow the old route are dropped by the filter before they leave.
App-level and system-level are not the same promise
The distinction is what happens when the client is not running.
An app-level switch is logic inside the client: it watches the tunnel’s state and, on detecting a drop, closes the connections it can reach. Its enforcement therefore depends on the client staying alive and staying attentive, and on the tunnel state it is watching being an accurate report of whether packets are moving.
A system-level switch installs rules into the operating system’s own filtering layer, which enforces them independently of the process that added them — exposed on mobile platforms as a setting disallowing connections without the tunnel, and on desktops as rules added by a privileged helper the client installs.
The difference shows up in the failure you did not plan for. If the client crashes, an app-level switch is gone along with the code that implemented it, and traffic flows normally with no indication that anything changed. A system-level rule set survives the crash — sometimes so thoroughly that you lose connectivity entirely until you reconnect or uninstall, which is unhelpful but is the correct direction to fail in.
Four moments when the rules are not yet in force
The switch protects the steady state; each of these is a transition out of it.
Before the rules are installed. A client that adds its filter rules after it has a tunnel leaves an interval in which the device has a working default route through the local network and no rule against using it. The length of that interval is a property of the client’s startup order, not of the switch, which is why two clients with the same feature list can behave differently here.
During a server change. Switching location tears down one tunnel and builds another. A careful client keeps the block in force across the transition; a less careful one removes the old rules before installing the new, producing a brief unprotected interval every time.
On reconnect after a drop. The client must let its own traffic reach the VPN server to re-establish, and it also has to re-resolve the server’s hostname if it does not have an address cached. That lookup is traffic, and where it goes during the gap is a real question — one of the reasons a leaked name lookup and a kill-switch failure so often appear together.
Waking from sleep. Interfaces come back in an unpredictable order and the client may take a moment to notice. This is the most commonly observed gap on laptops, because closing the lid is so routine.
None of these is a reason to leave the switch off. They are reasons not to treat it as a guarantee that traffic has never once left outside the tunnel.
What a kill switch structurally cannot do
It reacts to a tunnel that stops, which is not the only way a tunnel goes wrong.
It cannot recall anything already sent, and it cannot help with a tunnel that is up but broken. If the interface exists and the routes point at it, the rules are satisfied — even when the far end is dropping your packets, or when name lookups are answered by a resolver outside the tunnel while traffic goes through it. The filter checks which interface a packet used, not whether that interface is doing anything sensible.
It cannot protect other devices. It is a rule set on one machine, so everything else on your network is unaffected — one of the harder gaps to close on a router-based setup, per why a router VPN behaves differently from a VPN app.
It cannot cover an interface it does not know about. Rules written for one address family while the other is left routable is the classic version, and it is why IPv6 leaks survive kill switches that look correctly configured.
And it cannot make an excluded application safe. If you use split routing, some traffic is outside the tunnel deliberately, and clients differ on whether the switch blocks that too.
Finding out whether yours works
Cause the failure on purpose and watch, rather than trusting the checkbox.
Note your apparent public address with the tunnel connected, then start something producing continuous visible traffic. Now break the tunnel deliberately: on a desktop, disable the tunnel interface or stop the tunnel process rather than pressing the app’s disconnect button, which is a cooperative path the client handles gracefully and is not the failure you are testing. On a phone, toggling airplane mode is a rough equivalent.
If the switch is working, the visible traffic stops and stays stopped. If pages keep loading, or resume after a pause, traffic found the old route — and if your apparent address has reverted to your ordinary one at that moment, you have a definitive answer.
Two follow-ups complete the picture. Check name resolution separately from traffic, because they can fail independently; how to check for a VPN leak covers both and is my VPN leaking my IP covers what to conclude. And repeat the test after your next operating system update, since installed filtering rules are exactly what an update quietly invalidates.
The reasonable expectation
Treat it as a mechanism that closes the largest hole and leaves small ones at the edges. Enabled and at system level, it turns the common failure — tunnel drops, traffic silently continues — into an obvious outage you will notice. That is worth having, and it is not a promise that nothing ever escaped. If you need the stronger promise, keep the activity off the device rather than trusting a rule set with a startup window.