🔒 Routing specific traffic through VPN
Virtual Private Networks are crucial things in privacy or security and most of them are configured ready to use. Although by default those are routing everything through the VPN. That is not ideal in every case, sometimes it is enough to route only a part of the traffic and leave the rest on the physical interface. Taking examples of different cases this tutorial describes the steps needed to route specific traffic only over the VPN.
OpenVPN
This must be properly installed and configured to act as the VPN client. No providers application can be used here.
- Install OpenVPN and its dependencies:
sudo apt-get install openvpn
- Download
*.ovpn
config files from the provider's site. These are usually available to download as a compressed file. - Extract files in a subfolder of
/etc/openvpn/
. It is important to put those files in a subfolder, otherwise they gets interpreted as config files when starting the systemd service.sudo unzip ovpn_files.zip -d /etc/openvpn/servers
- Now all these files needs to be updated with the
route-nopull
option. This is to tell OpenVPN not to route anything, just create the connection and the interface.for file in /etc/openvpn/servers/* ; do echo -e "\nroute-nopull" >> $file; done
- Starting the VPN automatically on boot requires also to have the username and password preconfigured,
so it doesn't ask for it during the initialization of the connection. A single file is needed with
username
andpassword
in 2 lines.sudo nano /etc/openvpn/.secret
The file content should look something like this:
- Softlink one of the config files from the
subfolder
to theopenvpn
folder, but with a*.conf
extension. This connection will be initialized when the systemd service has been started.sudo ln -s /etc/openvpn/servers/nl123.vpn-provider.tcp.ovpn /etc/openvpn/nl123.vpn-provider.tcp.conf
- The OpenVPN service can be started now. It is going to create a (probably)
tun0
adapter, but not doing any routing so still unusable.sudo service openvpn start
Check if it is really up and running:ps aux | grep openvpn
ifconfig tun0
- Create a new routing table for the purpose by adding an extra line with the tables name in the file
rt_tables
.echo -e '\n200\tmy_table' | sudo tee --append /etc/iproute2/rt_tables > /dev/null
</li>
- Define a new default route and gateway to the new connection. The gateway
1.2.3.4
have to be replaced with thetun0
's gateway. This is usually the ip address of the interface, but the last group of numbers is1
. Like1.2.3.1
sudo ip route add default via 1.2.3.4 dev tun0 table my_table
- Add a new rule to the ip table for redirecting marked packages on the above defined route:
sudo ip rule add fwmark 0x1 table my_table
- Disable the reverse path filtering on all interface to let the routing work with this config:
for f in /proc/sys/net/ipv4/conf/*/rp_filter; do echo 0 > $f; done echo 1 > /proc/sys/net/ipv4/route/flush
username passwordWhen done editing, don't forget to change permissions properly:
sudo chmod 600 /etc/openvpn/.secret
The VPN is already usable for now, but only by applications which supports a bind option. Since not all of them have one here comes two options for redirecting traffic on the VPN.
Redirect based on port
- Mark the packets on specific port to be redirected, for example the http port 80:
sudo iptables -A OUTPUT -t mangle -o eth0 -p tcp --dport 80 -j MARK --set-mark 1
- Redirect every packet with a mark and rewrite the source ip address. Don't forget to replace the ip
1.2.3.4
!sudo iptables -A POSTROUTING -t nat -o tun0 -p tcp --dport 80 -j SNAT --to 1.2.3.4
Redirect based on multiple ports range
- Mark the packets on specific port-range to be redirected, for example the ports between 6884-6889:
sudo iptables -A OUTPUT -t mangle -o eth0 -p tcp --match multiport --dports 6884:6889 -j MARK --set-mark 1
- Redirect every packet with a mark and rewrite the source ip address. Don't forget to replace the ip
1.2.3.4
!sudo iptables -A POSTROUTING -t nat -o tun0 -p tcp --match multiport --dports 6884:6889 -j SNAT --to 1.2.3.4
Redirect based on user
- Mark the packets from a specific user to be redirected. Don't forget to change the user-id
1002
:sudo iptables -A OUTPUT -t mangle -o eth0 -p all -m owner --uid-owner 1002 -j MARK --set-mark 1
- Redirect every packet with a mark and rewrite the source ip address. Don't forget to replace the ip
1.2.3.4
!sudo iptables -A POSTROUTING -t nat -o tun0 -p all -j SNAT --to 1.2.3.4
Ready to test
After it is all set-up, possible to check if it properly working by issuing the following:
tcpdump -i tun0 -n
Or by simply checking the current ip:
curl icanhazip.com