Preventing VPN leaks on Linux

A Raspberry Pi running OpenVPN with a D-Link DUB-1312 Ethernet adapter
A Raspberry Pi model B running OpenVPN with a D-Link DUB-1312 Ethernet adapter

In a previous post I showed how a firewall app on Android can prevent metadata leaks when you connect to a wireless network but have not yet connected to your VPN. This guide achieves the same goal with OpenVPN or Torguard Lite on a Linux PC, blocking all outgoing connections and then allowing connections only to the VPN server.

This guide assumes that you are connecting to your VPN on UDP port 443, or on a known IP address. Visit an IP address checker such as IPLeak to confirm that your VPN is working before you start changing your firewall settings.

My ethernet port facing the internet (connected to the modem) is called eth0. The VPN connection is called tun0. Your network interfaces might be named differently. You can see a list of all network interfaces with the ifconfig command.

All these commands must be run as the root user or with sudo.

Begin by deleting all existing firewall rules:

iptables --flush
iptables --delete-chain
iptables -t nat --flush
iptables -t nat --delete-chain

Block all outgoing connections by default:

iptables -P OUTPUT DROP

Allow the special loopback device:

iptables -A INPUT -j ACCEPT -i lo
iptables -A OUTPUT -j ACCEPT -o lo

Method 1: Allow outgoing connections only for DNS and OpenVPN. This is simpler, but you might leak DNS lookup requests on port 53 when your VPN is disconnected:

iptables -A OUTPUT -j ACCEPT -p udp --dport 53
iptables -A OUTPUT -j ACCEPT -p udp --dport 443

Method 2: Alternately, you can allow outgoing connections to only specific IP addresses for your VPN servers. This method is immune to DNS leaks when the VPN is disconnected, but you will need to know the IP address of your VPN servers:

iptables -A OUTPUT -j ACCEPT -d 190.93.241.85
iptables -A OUTPUT -j ACCEPT -d 141.101.241.85
iptables -A OUTPUT -j ACCEPT -d 89.248.172.45

Finally allow outgoing connections through the VPN interface tun0:

iptables -A OUTPUT -j ACCEPT -o tun0

You should now be able to connect to your VPN server:

torguardlinux4

When the VPN is disconnected you should have no internet access:

torguardlinux5

IMPORTANT: Your firewall settings will be forgotten after you reboot. Save your list of commands in a bash file called /root/firewall.sh and remember to include the bash header. You can also include your command to launch OpenVPN here!

#!/bin/bash
iptables --flush
iptables --delete-chain
iptables -t nat --flush
iptables -t nat --delete-chain
iptables -P OUTPUT DROP
iptables -A INPUT -j ACCEPT -i lo
iptables -A OUTPUT -j ACCEPT -o lo
iptables -A OUTPUT -j ACCEPT -p udp --dport 53
iptables -A OUTPUT -j ACCEPT -p udp --dport 443
iptables -A OUTPUT -j ACCEPT -o tun0
openvpn /root/config.ovpn

Set it to run on boot by adding this line to the end of /etc/crontab:

@reboot root /root/firewall.sh