The menu offers Disconnect, the window has a close button, and the task manager offers End task. Each looks like a way to stop the VPN, and each can leave the machine in a different state. One may stop the tunnel while leaving a block in place, another may clean up everything as part of a graceful exit, and a third may merely hide the interface while the background component keeps running. Treating those as synonyms is how a privacy test reaches the wrong conclusion about what happened.

The client documentation is the only reliable place to learn which is which.

Four Controls, Possibly Four Behaviours

Disconnect usually tears down the tunnel while the client stays resident, which means a service, tray component or kill-switch rule can survive the click. Many clients then keep blocking traffic because their policy says the device must not fall back to direct access while the client is present. That behaviour looks like a broken network and is deliberate protection.

Quit is meant to end the application, and a well-behaved client removes its rules on the way out. Some designs instead leave a separate helper enforcing policy, which is a choice rather than a defect. Closing the window is a user-interface action with no defined effect on the tunnel, and Pause, where offered, is a fourth behaviour with its own rules.

A server-side outage is a fifth path entirely, and it is the one users actually encounter most often.

Read the State Before and After Each Action

Capture the process list, the service state and the firewall rules before the action, then repeat the capture immediately afterwards. Comparing the two lists shows what the control really did, without relying on the interface's own description.

systemctl status wg-quick@wg0 --no-pager
pgrep -a -f 'openvpn|wireguard|vpnagent'
ip link show | grep -E 'tun|wg'
nft list ruleset | grep -E 'drop|reject' | head -20
scutil --nc list

If rules disappear together with the process, the client owned them. If rules remain while the process is gone, something else enforces the policy, and finding that component comes before any change. Record the service state at the same moment, because a stopped user interface says nothing about a system service.

A Manual Disconnect Is Not a Crash

Disconnecting runs the intended shutdown path, and a crash skips it. Results from one therefore do not transfer to the other, so a test that used a menu item cannot support a claim about behaviour when the client dies.

In the same way, a crash tells you nothing about an approved temporary pause. Keep those three questions separate in the test plan and in whatever gets written down afterwards. The shutdown path also explains why a clean exit can remove rules that a crash leaves behind. Same button, different code, different evidence.

Pick the Unavailable State You Actually Need

If traffic must stay blocked whenever the tunnel is down, verify that requirement during the specific action you care about, using harmless traffic to a known destination. Include application exclusions and local-network exceptions, because device-wide enforcement is often narrower than its label suggests. Then confirm what happens after a reboot, since that is when stale state usually appears.

If the goal is ordinary direct access, use the documented control rather than killing processes or disabling the whole firewall. Stale rules left by an interrupted exit are a different problem from an intentional lockdown, and they need a different recovery.

Write down which component stopped: the tunnel, the visible application, or the layer enforcing policy. That one sentence prevents most of the confusion these controls create.

Ngaahi tokoni fekau'aki