I've adapted this kill switch solution from Reddit. I created a Bash script in my home directory named ~/pn-check.sh:
#!/bin/bash
Bring the interface en0 up
/sbin/ifconfig en0 up
sleep 1 # Wait for the interface to come up
Run sshuttle, and if it fails, bring en0 down and send a macOS notification
/opt/homebrew/bin/sshuttle -vr xxx@123.123.123.123 0/0 --ssh-cmd "ssh -i /Users/dara/.ssh/id_ed25519" || {
/sbin/ifconfig en0 down
osascript -e 'display notification "No longer protected. check vpn-check.sh in home and com.dara.script.plist" with title "Error"'
}
I then added this to a Plist named com.dara.script.plist: ~/Library/LaunchAgents/com.dara.script.plist; feel free to change the name to better match your setup.
Also note that the path to ~/pn-check.sh is explicitly set to /Users/dara/vpn-check.sh but it should be changed to match your environment:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>com.dara.script</string>
<key>ProgramArguments</key>
<array>
<string>/usr/bin/sudo</string>
<string>/Users/dara/vpn-check.sh</string>
</array>
<key>RunAtLoad</key>
<true/>
<key>KeepAlive</key>
<true/>
<key>StandardErrorPath</key>
<string>/tmp/script.err</string>
<key>StandardOutPath</key>
<string>/tmp/script.out</string>
</dict>
</plist>
It seems to be quite robust! Losing network connection doesn't reset sshuttle and if I manually kill the command macOS retries the script every few seconds.