VPN kill switch for macOS. Blocks all outgoing traffic when the VPN connection drops, preventing your real IP from leaking.
When enabled, killswitch loads pf firewall rules that only allow traffic through the VPN tunnel. If the VPN disconnects, the tunnel interface disappears but the firewall rules remain — blocking all internet traffic until the VPN reconnects or the kill switch is disabled.
Rules are written to /tmp/killswitch.pf.conf and loaded with pfctl.
The system default /etc/pf.conf is never modified.
Show network interfaces, public IP, and detected VPN peer:
$ killswitch
Enable the kill switch (requires root):
$ sudo killswitch -e
Disable and restore default firewall rules:
$ sudo killswitch -d
Print the firewall rules without applying them:
$ killswitch --print
| Flag | Description |
|---|---|
--leak |
Allow ICMP (ping) and DNS requests outside the VPN |
--local |
Allow local network traffic |
--ipv4 <IP> |
Manually specify the VPN peer IP (auto-detected if omitted) |
-v, -vv |
Verbose / debug output |
Enable with DNS leak and local network access:
$ sudo killswitch -e --leak --local
Specify the VPN peer IP manually:
$ sudo killswitch -e --ipv4 203.0.113.1
Preview rules in debug mode:
$ killswitch --print --leak -vv
The VPN gateway IP is auto-detected using multiple methods (in order):
- sysctl — reads the kernel routing table directly
- netstat — parses routes with
UGSH/UGScflags - scutil — queries macOS Network Extension services (works with WireGuard, ProtonVPN, etc.)
- ifconfig — extracts peer addresses from tunnel interfaces
If auto-detection fails, use --ipv4 to specify the VPN peer IP manually.
Requires Rust:
$ cargo build --release
$ sudo cp target/release/killswitch /usr/local/bin/
$ just test # format check + clippy + tests
$ just fmt # check formatting
$ just clippy # lint all targets