This guide explains how to use a VPN service to selectively route torrent traffic only, leaving all other Internet access on the computer unaffected.
This guide assumes a Linux workstation. Sorry Windows users, but I have no idea if something like this is possible on your OS.
This solution makes use of 2 key concepts:
- The Linux kernel supports multiple routing tables (http://linux-ip.net/html/routing-tables.html).
- IP packets can be easily marked with a unique marker, and routed to a specific routing table based on that marker.
This implementation is based on creating a dedicated user that will be used for running your torrent software. Then we use iptables to mark all packets originating from that user with our special marker that will route the traffic to our special routing table that will send all traffic through the VPN. That way all other users remain unaffected.
In my case I decided to use NordVPN (https://nordvpn.com). Any other VPN provider will work, as long as it is possible for you to connect using the amazing OpenVPN software (https://openvpn.net/).
So the first step is to make sure that you can connect to your VPN with OpenVPN. The instructions for NordVPN are found here: https://nordvpn.com/tutorials/linux/openvpn/
After you have that working, proceed to the next step.
First, we need to comment out any authentication options specified in the OpenVPN config file you downloaded from your VPN provider. In my case, I had to comment out the ‘auth-user-pass‘ directive, because I didn’t want OpenVPN to ask me for my credentials every time. I want the connection to authenticate automatically, so I opened the config file for my selected server and commented out the line:
We’ll specify a different way to authenticate later.
Next, we need to change a couple of kernel parameters so that we can route the packets the way we want. We’ll need to edit /etc/sysctl.conf and add the following lines:
net.ipv4.ip_forward = 1 # Enable IP Forwarding net.ipv4.conf.default.rp_filter = 0 # Disable Source Route Path Filtering net.ipv4.conf.all.rp_filter = 0 # Disable Source Route Path Filtering on All interfaces
and then run:
sudo sysctl -p /etc/sysctl.conf
to activate your new settings.
Next, create a user just for your torrent program. You’ll also want to make sure that your torrent program is always started by this user. The reason for this is that iptables has an “owner” packet matching plugin which matches all outgoing packets belonging to a specific UID. You can use this to put a mark on all packets belonging to that user which can be used by the kernel to route those packets through a specific interface.
In this guide we’ll assume that the user is called ‘torrents‘.
You are now ready to copy-and-paste some startup scripts that will set everything up for you when your computer boots.
openvpn \ --log-append /var/log/openvpn/nordvpn-client.log \ --route-noexec \ --script-security 2 \ --up-delay \ --up /etc/openvpn/nord_vpn_callback_up.sh \ --auth-user-pass /etc/openvpn/nord_vpn_auth.txt \ --config /etc/openvpn/ovpn_tcp/ca306.nordvpn.com.tcp.ovpn
Note: The last line is where you specify the OpenVPN config file for the specific VPN server you wish to use.
#!/bin/sh # User defined config # export USER_NAME='torrents' # VPN will be enabled only for this user export PACKET_MARKER=3 # Arbitrary packet marker<span id="mce_SELREST_start" style="overflow:hidden;line-height:0;"></span> export ROUTING_TABLE_NUMBER=200 # Arbitrary routing table number # These enviroment variables are set by OpenVPN. # See manpage 'Environmental Variables' section. # export TUN_DEV=$dev export VPN_LOCAL_IP=$ifconfig_local export VPN_GATEWAY_IP=$route_vpn_gateway
#!/bin/sh . /etc/openvpn/nord_vpn_common_setup.sh echo "================================================" echo " --- Hooking up to Nord VPN ---" echo "================================================" echo "VPN Interface: $TUN_DEV" echo "VPN Local IP: $VPN_LOCAL_IP" echo "VPN Gateway IP: $VPN_GATEWAY_IP" echo if [ -z "$VPN_GATEWAY_IP" ] ; then echo "ERROR: Not all expected parameters were present!\n" exit 1 fi # Just in case we didn't clean up before. echo "\nCleaning up from previous run..." ip rule delete fwmark $PACKET_MARKER ip route flush table $ROUTING_TABLE_NUMBER # Attach a marker to all packets coming from processes owned by the user echo "\nInserting iptables rules..." iptables -t mangle -A OUTPUT -m owner --uid-owner $USER_NAME -j MARK --set-mark $PACKET_MARKER # Everything that leaves over the VPN's TUN device should have the source address set currectly. # Apparently some torrent clients mistakenly grab the address from eth0 instead, which makes # the VPN drop those packets. This corrects any such packets with bad source address. iptables -t nat -A POSTROUTING -o $TUN_DEV -j SNAT --to-source $VPN_LOCAL_IP echo "\nMANGLE OUTPUT:" iptables -t mangle -L OUTPUT echo "\nNAT POSTROUTING:" iptables -t nat -L POSTROUTING # Everything that is marked with $PACKET_MARKER should be routed to our custom routing table echo "\nForwading all packets marked with $PACKET_MARKER to the new routing table $ROUTING_TABLE_NUMBER...." ip rule add fwmark $PACKET_MARKER lookup $ROUTING_TABLE_NUMBER ip rule # All traffic destined for the LAN should go over eth0, not the VPN echo "\nRouting LAN packets to eth0..." ip route add 192.168.0.0/24 dev eth0 table $ROUTING_TABLE_NUMBER # Everything else should be routed via the VPN device echo "\nRouting all external traffic to the VPN Gateway $VPN_GATEWAY_IP..." ip route add default via $VPN_GATEWAY_IP dev $TUN_DEV table $ROUTING_TABLE_NUMBER if [ $? -ne 0 ]; then echo "ERROR: Could not add default route $VPN_GATEWAY_IP!\n" exit 2 fi # Show the new routing table ip route list table $ROUTING_TABLE_NUMBER echo echo "\nVPN is connected!\n" ifconfig $TUN_DEV echo
Your Username Your Password
#!/bin/sh . /etc/openvpn/nord_vpn_common_setup.sh echo "================================================" echo " --- Cleaning up after Nord VPN ---" echo "================================================" echo echo "Removing iptables rules..." iptables -t mangle -D OUTPUT -m owner --uid-owner $USER_NAME -j MARK --set-mark $PACKET_MARKER iptables -t nat -D POSTROUTING -o $TUN_DEV -j SNAT --to-source $VPN_LOCAL_IP echo "\nMANGLE OUTPUT:" iptables -t mangle -L OUTPUT echo "\nNAT POSTROUTING:" iptables -t nat -L POSTROUTING echo "\nRemoving custom routing table $ROUTING_TABLE_NUMBER...\n" ip rule delete fwmark $PACKET_MARKER ip route flush table $ROUTING_TABLE_NUMBER ip route echo ip rule echo
NOTE: This script is provided for your convenience when you wish to shut down the VPN manually for some reason. We are purposefully not attaching it to OpenVPN’s down-hook. This provides us with our own “kill switch” functionality. If the VPN goes down for whatever reason, your torrents will stop working, rather than smoothly transitioning to non-encrypted downloads without telling you.
echo "Starting NordVPN..." /etc/openvpn/nord_vpn_start.sh & exit 0
The above is one of many ways to start your VPN at boot.
And that’s it. Hope it helps.
Everything in this guide is based on the following Reddit post. All I did here is provide the actual scripts to make the setup easier.