Kill switches and no-overlap rules point in opposite directions, which explains why ordinary VPN settings never express the second one. The kill switch reacts to a tunnel that has gone down, while this requirement reacts to a tunnel that is up and keeps an application out of the picture. One design decision settles most of it: whether the application is stopped, blocked from starting, or merely stripped of network access. Pick that layer before reaching for a firewall rule or a process-killer loop, because a rule enforced by observation leaks a window on every launch.

The Myth: A Kill Switch Stops Programs From Starting

Kill switches are traffic controls, and they are honest about it: they permit or deny packets according to tunnel state. None of them refuse to start a program, and none inspect which executable opened a socket. A desktop shortcut, a scheduled task and a background helper all reach the network without passing anything that knows the application's name. The distance between those two mechanisms is where most of the confusion lives.

The arrangement that does decide whether a program may start is application control. On Windows that means AppLocker or WDAC, and on managed macOS it means an allowlist enforced by the device profile. Both are independent of the tunnel, which is why the two requirements get merged in the same ticket and then satisfied by neither.

Name the Mode Before You Name the Tool

Write the rule as a state machine with three states: ordinary use, VPN work session, and leaving. The forbidden overlap belongs to the middle state, not to the client software.

Whoever changes the state owns three actions in order: finish the application's work, request its normal shutdown, and confirm the instance is gone before the tunnel comes up. Ordering matters at the other end too, because a VPN that connects first and stops the program second has already allowed the overlap. If the requirement covers connection establishment, waiting for a connected indicator is too late.

What a Two-Way Conflict Really Does

For two services genuinely managed by systemd, Conflicts= is symmetric: starting one stops the other. The unit reference documents that behaviour and separately requires explicit ordering when one must finish stopping before the other starts. Without those ordering entries the stop and the start race, and the outcome depends on timing.

That is not a denylist. Wire the dependency the wrong way round and starting the application stops the VPN instead, which is the failure to suspect when a tunnel disconnects by itself at a predictable moment. A desktop application is not a systemd unit, and a NetworkManager connection is not one either, so this pattern works only for services you wrap yourself.

Check the Transitions, Not Just the First Launch

Four transitions decide whether the requirement holds: entering the session with the application running, launching it again mid-session, a failed VPN start, and a deliberate disconnect. Test each one and keep the result next to the unit files. The commands below read the current relationship and then exercise the transition that matters most.

systemctl show work-vpn.service -p Conflicts -p After
systemctl start work-vpn.service
systemctl is-active office-sync.service
nmcli connection show --active

The third command should leave the application inactive, and the fourth should list only the tunnel connection while a session is running. A different result means the transition is not enforced at all.

A relaunch during the session is the case that exposes a wrapper-based design, since a shortcut started from the desktop never consults a launcher script. If that bypass matters, enforcement belongs in application control and not in the VPN client. Document the end of the session as well, and prefer a deliberate resume over reopening every process that was stopped on the way in. Record the result of each transition in the same note that holds the unit files.

ተዛመድቲ ጽሑፋት