What do you think? Discuss, post comments, or ask questions at the end of this article [More about me]

For the security and privacy conscious, a trusted VPN is a great tool that provides encrypted communications and assured privacy while accessing unsecured networks (the internet in particular). 

I use several VPNs, I have my own private OpenVPN server which I run on my main (personal) server, and also use a well known VPN service.   I do use both (not at the same time) for various purposes and for different use cases which won't be discussed here.

One of the important reasons for using a VPN is to obfuscate (hide) your ip address.  It's important to note that even the best VPN setups are subject to occasional drops and disconnects.  When this occurs, your system will likely fallback to using its standard network interfaces (which it would use without a VPN) and incidentally expose your actual ip address.  In sensitive environments (or countries) this can potentially lead to some very undesirable situations (including being able to find your actual location).

Enter a Kill Switch.  A kill switch is basically some system which ensures your ip address is not leaked, and ideally blocks all traffic that is not through the VPN.  Hence if your VPN connection drops, your system doesn't fall back to standard network interfaces.

Many VPN services provide built in Kill Switch functionality.  However, I generally prefer to roll my own, with an implementation that I trust (because I did it).

Guide

Requirements and setup

This implementation doesn't require much.  Basically you need

  • bash
  • sudo access
  • ufw (uncomplicated firewall)

All Linux distros should have these (mostly likely by default).

Make sure UFW is setup and installed.  For distros that use systemd, you would simply do

sudo systemctl enable ufw
sudo ufw enable

vpnkillswitch scripts

My killswitch consists of a single bash script.  This script supports both starting the killswitch and stopping the killswitch (which resets the firewall), plus another option to open an outgoing route to a specific CIDR:

#!/bin/bash

# process arguments
while getopts ":edt:" opt; do
	case ${opt} in
		e)
			# ENABLE KILLSWITCH
			# Default policies
			sudo /usr/bin/ufw default deny incoming
			sudo /usr/bin/ufw default deny outgoing
			
			# Openvpn interface (adjust interface accordingly to your configuration)
			sudo /usr/bin/ufw allow out on tun0

			# Openvpn (adjust port accordingly to your vpn setup)
			sudo /usr/bin/ufw allow out to any port 1194
			;;
		d)
			# DISABLE KILLSWITCH
			sudo /usr/bin/ufw --force reset
			sudo /usr/bin/ufw enable

			# delete backUP rules from reset
			sudo /usr/bin/rm /etc/ufw/*.rules.*
			
			# reset to defaults and enable
			sudo /usr/bin/ufw default deny incoming
			sudo /usr/bin/ufw default allow outgoing
			;;
		t)	
			# ADD OUTGOING RULE
			echo "allow outgoing traffic to $OPTARG"
			sudo /usr/bin/ufw allow out to $OPTARG
			;;
	esac
done

if (( $OPTIND == 1 )); then
	echo " "
	echo -e "Please provide at least one of the following options:\n    -e"
	echo "        enable killswitch"
	echo "    -d"
	echo "        disable killswitch"
	echo "    -t [CIDR]"
	echo -e "        open outgoing ufw rule to a specific CIDR (ip address or range)\n"
fi

You'll need to make the script executable and ideally put it in some folder on your path.  To make them executable, cd into whatever folder contains the scripts and:

chmod +x vpnkillswitch

Usage

Basic usage is to simply call the script with a valid option.  The supported options are:

-e
	enable killswitch (turn it on)

-d
	disable killswitch (turn it off)

-t [CIDR]
	open outgoing (ufw) route to a specific CIDR (ip address or range)	

Note that the -t  option will likely be needed if you also run a web server (for example) on the same server that is running your VPN and want to access web server resources.

Examples

Turn on (enable) the killswitch

vpnkillswitch -e

Turn on (enable) the killswitch and allow outgoing route to to some server, e.g. 93.184.216.34:

vpnkillswitch -et 93.184.216.34

Turn off (disable) the killswitch

vpnkillswitch -d

Integrating killswitch into OpenVPN client ovpn

If you (or your VPN provider) uses OpenVPN you can integrate the killswitch script into your client .ovpn  file so that when you connect the killswitch script is automatically run.  This comes in handy especially if you run your own OpenVPN server (which I do) - and also use that server for other things (such as a web server etc.).  In these types of use cases you can also open an outgoing route to your server (for example to access server web resources while also being connected to said server via OpenVPN).

You can simply add a up  or route-up  directive with the vpnkillswitch  command.  For example, in my client .ovpn  I simply added:

script-security 2
route-up "/home/user/.local/bin/vpnkillswitch -et <IP-ADDRESS-OF-OPENVPN-SERVER>"

Replace <IP-ADDRESS-OF-OPENVPN-SERVER> with the IP address of the outgoing route you want to allow.

I use  route-up   here as OpenVPN will execute the script after routes to the VPN server has been added.  This is after any   up  commands have been run (which you might use in your client config to set DNS addresses etc.).

Don't forget that you'll need to disable the kill switch after disconnecting with from OpenVPN.  You can do this by executing:

vpnkillswitch -d

References

  1. https://thetinhat.com/tutorials/misc/linux-vpn-drop-protection-firewall.html