From my website: https://www.gianttree.de/blog/2017/10/21/how-to-make-sure-all-your-network-traffic-is-routed-through-your-vpn
The issue
How to make sure all your network traffic is routed through your VPN?
That's a question many people can't easily answer. Typical VPN setups rely on the prioritization of the operating system to route network traffic through the VPN. This setup works but connections from the outside are still coming in and once the connection to the VPN closes, the normal connection is used seamlessly.
This is nice but it defeats the purpose of a VPN for some folks as it might leak data through and because of unsecured connections (see the latest news about the KRACK vulnerability in WPA2).
What can you do about this issue?
There are multiple ways to combat the issue of disconnecting from a VPN: kill-switches that kill specific applications or black-holes that discard any non-VPN traffic.
In this article I will walk you through the steps needed to configure your Linux system to prevent any data being send to any destination that isn't your VPN.
The prerequisites
In order to configure everything to prevent data leakage we need a few things to be setup first:
- A network and internet connection; it doesn't make sense to secure a connection that is non-existent.
- A keyboard (a mouse is optional).
- Root access on the system in question.
Actually securing the connection and preventing data leaking
The examples here are all done on a Debian 9 system but should be applicable to most Linux distributions.
All the commands assume your primary network connection to be on eth0
and your VPN to be on tun0
.
The local network in these examples is on 192.168.0.0/24
.
Installing the necessary packages
Whilst using bare-to-the-metal applications is one way of configuring a firewall, I will be using ufw
, a wrapper around iptables
.
So first we install ufw
:
apt install ufw
That should be the first step done.
There is just one caveat: ufw
is disabled by default because it would prevent incoming connections like ones over SSH. Before we activate ufw
, we have to set up our rules.
Adding the necessary rules to ufw
By default ufw
allows all outgoing traffic, this is great for ordinary use-cases but some applications send out data we don't want to be routed through the internet before going through our VPN.
ufw
also reads rules from the top to the bottom: beginning with rule 1, going through each of them and applying the first rule that matches. This behaviour is inherited from iptables
.
So to begin, we allow local network traffic, that way we don't accidentally prevent ourselves from connecting to our system over SSH:
ufw allow in on eth0 from 192.168.0.0/24
ufw allow out on eth0 to 192.168.0.0/24
Now that we can reach our local network, we can enable the firewall and deny outgoing connections that are not explicitly allowed:
ufw enable
ufw default deny outgoing
Querying ufw
about its status reveals the installed rules:
# ufw status verbose
Status: active
Logging: on (low)
Default: deny (incoming), deny (outgoing), allow (routed)
New profiles: skip
To Action From
-- ------ ----
Anywhere on eth0 ALLOW IN 192.168.0.0/24
192.168.0.0/24 ALLOW OUT Anywhere on eth0
Pinging a known IP like 8.8.8.8
fails spectacularly, just like we configured:
# ping 8.8.8.8
PING 8.8.8.8 (8.8.8.8) 56(84) bytes of data.
ping: sendmsg: Operation not permitted
ping: sendmsg: Operation not permitted
^C
--- 8.8.8.8 ping statistics ---
2 packets transmitted, 0 received, 100% packet loss, time 1013ms
Now even our VPN is blocked, so let's allow our system to connect to our VPN (replace <VPN IP>
with the ip address or network of your VPN):
ufw allow in on eth0 from <VPN IP>
ufw allow out on eth0 to <VPN IP>
Connecting to our VPN works fine now, but traffic through the VPN tunnel itself is still blocked by our default rule:
# ip a
...
4: tun0: <POINTOPOINT,MULTICAST,NOARP,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UNKNOWN group default qlen 100
link/none
inet 10.7.7.18/24 brd 10.7.7.255 scope global tun0
valid_lft forever preferred_lft forever
# ping 8.8.8.8 -I tun0
PING 8.8.8.8 (8.8.8.8) from 10.7.7.18 tun0: 56(84) bytes of data.
ping: sendmsg: Operation not permitted
ping: sendmsg: Operation not permitted
^C
--- 8.8.8.8 ping statistics ---
2 packets transmitted, 0 received, 100% packet loss, time 1020ms
So let us allow traffic through the VPN tunnel now:
ufw allow in on tun0 from any
ufw allow out on tun0 to any
Verifying our rules
Lastly we verify our rules to make sure that all traffic through our VPN is allowed but traffic through our ordinary connection is restricted to local and VPN traffic only:
# ping 8.8.8.8 -I tun0
PING 8.8.8.8 (8.8.8.8) from 10.7.7.18 tun0: 56(84) bytes of data.
64 bytes from 8.8.8.8: icmp_seq=1 ttl=56 time=49.4 ms
64 bytes from 8.8.8.8: icmp_seq=2 ttl=56 time=48.4 ms
64 bytes from 8.8.8.8: icmp_seq=3 ttl=56 time=49.1 ms
^C
--- 8.8.8.8 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2003ms
rtt min/avg/max/mdev = 48.476/49.017/49.405/0.394 ms
# ping 8.8.8.8 -I eth0
PING 8.8.8.8 (8.8.8.8) from 192.168.0.2 eth0: 56(84) bytes of data.
ping: sendmsg: Operation not permitted
ping: sendmsg: Operation not permitted
^C
--- 8.8.8.8 ping statistics ---
2 packets transmitted, 0 received, 100% packet loss, time 1002ms
# ping <VPN IP> -I eth0
PING <VPN IP> from 192.168.0.2 eth0: 56(84) bytes of data.
64 bytes from <VPN IP>: icmp_seq=1 ttl=54 time=42.7 ms
64 bytes from <VPN IP>: icmp_seq=2 ttl=54 time=41.2 ms
64 bytes from <VPN IP>: icmp_seq=3 ttl=54 time=41.8 ms
^C
--- <VPN IP> ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2003ms
rtt min/avg/max/mdev = 41.275/41.951/42.750/0.630 ms
Conclusion
The steps above are all that is necessary to filter IP packets and deny any stray packets that want to leave on your primary, non-VPN connection but still allow you to communicate with local services like DNS or DHCP and connect to the system using SSH, FTP and more.
References
UFW page on the Ubuntu Community Help Wiki
UFW tutorial by DigitalOcean
Gufw - a frontend for ufw
Congratulations @gianttree! You have completed some achievement on Steemit and have been rewarded with new badge(s) :
Award for the number of upvotes
Click on any badge to view your own Board of Honor on SteemitBoard.
For more information about SteemitBoard, click here
If you no longer want to receive notifications, reply to this comment with the word
STOP
Congratulations @gianttree! You received a personal award!
Click here to view your Board
Congratulations @gianttree! You received a personal award!
You can view your badges on your Steem Board and compare to others on the Steem Ranking
Vote for @Steemitboard as a witness to get one more award and increased upvotes!