Automating Transmission(Torrent) to use VPN while everything else uses standard connection.

I've wanted to write up a tutorial on how to script the set up for getting Transmission to use a VPN connection, including inbound connections but havent had much time until now. I've read many articles using jails(I dont use jails), other distros and all of that helped me get it working on my rig running FreeBSD 12. But to be honest I have been using the same set up since FBSD10. Now onto the tutorial.



I will assume that you know how to use the ports tree to download and install OpenVPN as well as the Transmission-daemon and Transmission-web.

Once those packages are installed we can get down to configuration. One thing to note I use PrivateInternetAccess(PIA) as my VPN provider as they provide open incoming ports. This will allow other torrent users to connect to you and speed up your downloads as sharing ratios go up. I'm not sure how this will apply to other vendors.



As we will not be using firewall rules to direct traffic around, my rig is behind and hardware firewall, we will be using setfib to assign the VPN network only to the Transmission application.



To allow for setfib correctly you will need to set the following system options in /boot/loader.conf

Check to make sure that sysctl shows that net.inet.ip.forwarding: 1 and net.fibs: 2, if not correct that in /boot/loader.conf

Code:
$ sysctl net.inet.ip.forwarding
net.inet.ip.forwarding: 1
$ sysctl net.fibs
net.fibs: 2

Once those system variables are set we will need to set up OpenVPN and the supplementary scripts.

1. Create a directory where you will build this process

mkdir ~/pia_vpn/
cd ~/pia_vpn/

2. Download the openvpn scripts to all the PIA configuration files. Be sure to use one that is not based in the USA as they do not allow inbound port forwarding. I use the Canadian based configs with the following modifications:

$ sudo wget https://www.privateinternetaccess.com/openvpn/openvpn.zip

Unizip the file and open the Toronto(or whichever location) based UDP config script and make the following changes. Be sure to compare the default scripts to what i have listed below there are several very important calls the need to be in the script to do a variety of functions like re-establishing a connection when it goes down automatically, calling the startup scripts, setting security level etc.

Code:
client
dev tun
proto udp
remote ca.privateinternetaccess.com 1194
resolv-retry infinite
nobind
persist-key
cipher BF-CBC
auth sha1
tls-client
route-nopull
remote-cert-tls server
auth-retry interact
auth-user-pass /usr/home/laundry/pia_vpn/pia_pass.txt
compress
verb 1
reneg-sec 0
crl-verify /usr/home/laundry/pia_vpn/crl.rsa.2048.pem
ca /usr/home/laundry/pia_vpn/ca.crt
script-security 2
up /usr/home/laundry/pia_vpn/set_route.sh
disable-occ
daemon

You will need to create a text file to store your login and password information so OpenVPN can login automatically.

vi /usr/home/laundry/pia_vpn/pia_pass.txt

It should only contain 2 lines

Code:
USER
PASSWORD

The password file needs to have only user read/execute so run the following command on the file:
chmod 700 pia_pass.txt

The other script that is called when the OpenVPN script bring up a connection is called set_route.sh. In the third line below I grep for tun1 because I have another VPN tunnel running so for you this may be tun0. This script creates the setfib route, binds and starts transmission to use it.

Code:
#!/usr/local/bin/bash
set -x
def_route_var=$(/usr/sbin/setfib 1 /usr/bin/netstat -4r | /usr/bin/grep tun1 | /usr/bin/awk '{print $1}')
echo "set default route with:  $def_route_var"
sudo /usr/sbin/setfib 1 /sbin/route add default $def_route_var
/usr/home/laundry/pia_vpn/start_apps.sh &

The set route script builds the route for setfib to use the VPN route and call a script start_apps.sh to actually bind and start Transmission. In start_apps.sh you will see that it calls the PIA API to get the current port to forward and modifies the transmission config files to use that as the incoming port. Again be wary of the directory names and change them according to your set up.

Code:
#!/usr/local/bin/bash
set -x
PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/games:/usr/local/sbin:/usr/local/bin:/home/laundry/bin
/usr/local/bin/sudo /usr/sbin/setfib 1 /usr/sbin/service transmission onestop
sleep 5
client_id=$(/usr/bin/head -n 100 /dev/urandom | /sbin/sha256 | /usr/bin/tr -d " -")
port_var=$(/usr/sbin/setfib 1 /usr/local/bin/curl "http://209.222.18.222:2000/?client_id=$client_id" 2>/dev/null|/usr/bin/cut -d ":" -f2|/usr/bin/cut -d "}" -f1)
echo $port_var >> /usr/home/laundry/pia_vpn/port_num.txt
/usr/bin/sed  -i -e "s/\"peer-port\".*/\"peer-port\": $port_var,/" /usr/transmission/home/settings.json
sleep 1
/usr/local/bin/sudo /usr/sbin/setfib 1 /usr/sbin/service transmission onestart

To tie this all together and have one script to call and start everything create the following script and call it vpnup.sh:

Code:
#!/usr/local/bin/bash
#set -x
echo "Stopping VPN"
pkill -u root openvpn
echo "Starting VPN"
openvpn /usr/home/laundry/pia_vpn/UDP_Toronto.ovpn
echo "Waiting for vpn to start..."
sleep 10
def_route_var=$(setfib 1 netstat -4r | grep tun1|awk '{print $1}')
var=$(ifconfig | grep -E 'inet.[0-9]' | grep -v '127.0.0.1' | grep -v '192.168.99' | grep -v '10.0.0.1'| awk '{ print $2}')
echo "VPN started IP: $var"
echo "VPN started with dafault route IP: $def_route_var"

In the previous script make sure you change the line to grep out (-v) localhost and whatever other IP ranges you have that do not match what PIA gives you. You only want to end up with the IP route for the VPN

Code:
var=$(ifconfig | grep -E 'inet.[0-9]' | grep -v '127.0.0.1' | grep -v '192.168.99' | grep -v '10.0.0.1'| awk '{ print $2}')

Start everything with:

sudo ./vpnup.sh

ACHTUNG !!! - Please remember to review the directory paths and match them to what you are using. Obviously I am hard coding my home directory which wont work for you!!!!
 
Back
Top