21

I have recently acquired a BeagleBone Black, onto which I've installed Ubuntu using this method. It has all worked so far. I want to use my BeagleBone as a torrent box, but I don't want to do it directly over my Internet connection (I don't think my ISP will like it) - so I've purchased a VPN subscription from a European server. I've manually connected my laptop to this VPN before and the run Transmission. I know that the VPN connection works in Ubuntu, and the host provides setup information for OpenVPN. Annoyingly, the dynamic nature of the assigned IP address means it would change frequently, so when I used my laptop with the VPN I would manually set the listening address in Transmission to the required value.

Ideally I'd like the following setup:

  • Transmission runs only over the VPN, and is prohibited from running torrents over the normal WAN connection
  • Only traffic directed to Transmission will be accepted or sent through the VPN, all other unsolicited traffic will be dropped
  • Transmission uses the appropriate port to listen on, based on the assigned IP address
  • OpenVPN starts automatically on boot, which then subsequently starts Transmission
  • Transmission's web GUI can be accessed over the LAN, and possibly over the Internet from my WAN connection (i.e. not back through the VPN)
seanlano
  • 2,986
  • 3
  • 28
  • 44

5 Answers5

24

Update: (2022-04-13) It's been quite a while, and I've got a new method for doing this, using Linux network namespaces. See my new answer for the steps. I'm also definitely not using that old Beaglebone board any more! The steps apply equally to any CPU type.


Note: (2016-02-22) I've realised this config leaks DNS queries to the torrent trackers through the normal WAN, instead of sending it through the VPN. I'm investigating how to fix this. I'm going to keep running my config though, since the connection itself does use the VPN properly.


Update: I've noticed that when I set Transmission to download overnight on the Beaglebone, CPU usage goes to 100% after a while. It doesn't seem to happen after the same amount of time, sometimes it's fine all night, other times it struggles after 10 minutes. It can also recover by pausing all torrents and waiting for CPU load to return to normal, then starting again. I'm still investigating. A workaround might be to pause and resume torrents periodically, although it's not a very good workaround. Note this issue only applies to the Beaglebone, and probably other ARM devices. I've never had this issue on a x86 CPU.


Introduction

I've developed and tested this solution for Ubuntu 14.04, running on a BeagleBone Black. The VPN provider I am using is called ibVPN. It should work with any supported hardware though (i.e. on a "normal" x86 computer), with any OpenVPN compatible VPN provider - and should probably work for 14.10 or later. At some point I believe Ubuntu will use SystemD for boot, which will mean the Upstart scripts used here will need to be migrated. Update: Jonas Kalderstam has an answer below for using SystemD. I'm also assuming that ufw is being used as the firewall, if you are using something different then the ufw commands here will need to be changed.

I assume that all work is done over an SSH connection to the system, although it would work just as well if typed out into a physical terminal.

This is quite a long tutorial, please read all of it first and make sure you are comfortable with what you will be doing.

I've also noticed that Transmission does not properly bind to an IP address for sending UPnP/NAT-PMP data - i.e. torrent data correctly goes through the VPN, but if UPnP port forwarding is enabled Transmission will request the port forward from the local router, not through the VPN from the VPN server. Hence I've made the Upstart script disable port forwarding, since it might appear as though it has worked, but it has not. It should be possible to use iptables and iproute to force all traffic from the debian-transmission user through the VPN, but I am still looking into this. It should also work if the default route was changed to send all Internet data through the VPN, but I didn't want to do that because I use this server for other things too, and this would also cause all system updates to come through the VPN. The effect of this is that Transmission will probably download torrents slower than it could if port forwarding worked - but I've found that reasonable speeds can be achieved for most torrents without port forwarding. This question has further information if you really want to get UPnP working over the VPN. Update: falk0069 has a fantastic tip below for helping to encourage UPnP over the VPN.

Installing and configuring OpenVPN

I'd recommend that you try getting your VPN connection to work using Ubuntu before trying to get it to work here - i.e. from a desktop. This will confirm that you have the correct configuration and reduce time spent debugging.

First, install the required packages

sudo apt-get install openvpn

Next, make a directory to store the configuration files in. I'm using /opt/ibVPN, since that's the provider I'm using. Change it to whatever you like.

sudo mkdir /opt/ibVPN

The first thing to do in this new directory is to create the config file for running the VPN client. ibVPN provides a basic config file for Linux users, which I've mostly just copied and pasted.

cd /opt/ibVPN
sudo vim config.ovpn

Copy and paste your edited version into vim, using the settings for your VPN provider. (FYI, paste in the Ubuntu terminal is Ctrl+Shift+V) You should be able to get this from your VPN provider.

remote 888.888.888.888 1194 udp      #This address will be different for you
client
dev tap1
resolv-retry infinite
script-security 3 system
explicit-exit-notify 3
persist-key
mute-replay-warnings
ca ibvpn.com.crt
comp-lzo
verb 3
mute 20
ns-cert-type server
fragment 1300
route-delay 2
reneg-sec 0
max-routes 5000
link-mtu 1578

auth-user-pass pass auth-nocache persist-tun route-noexec lport 1195 lladdr 00:FF:11:AA:BB:CC route-up "/opt/home/openvpn/route-up.sh" down "/opt/home/openvpn/down.sh"

For those unfamiliar with vim, press Insert to type or paste text, then press Escape and type :wq to save and quit. Of course, you don't have to use vim - any text editor will work.

I'll quickly explain this config file: The first 18 lines specify the specific settings to use with the server, these came from ibVPN - yours will probably be slightly different if you have a different provider. The next lines are modified options I've specified.

  • If your settings file had any lines with auth-user*, comment these out. For this setup to work automatically, we need to have a file with the username and password in it - so make sure the password you chose for the VPN provider is strong, random, and unique.

  • The auth-user-pass pass tells OpenVPN to look for a file called pass to read the user and password from.

  • auth-nocache removes the password from memory, which might slightly increase security if you are worried about it.

  • persist-tun will try to keep the same IP address from the server if your connection drops out, which should hopefully mean less starting and stopping of Transmission-daemon.

  • route-noexec tells the OpenVPN client not to automatically use the routes provided by the server - which would pull all network traffic over the VPN. We just want to send torrent traffic, so we will need to use different routing settings.

  • lport 1195 tells the OpenVPN client to use port 1195 instead of 1194 - in my case I also want to run an OpenVPN server on the same device, and the server will need to use port 1194. Even if you aren't running an OpenVPN server, it doesn't hurt to make this change.

  • I changed the line dev tap to dev tap1, to force the virtual device to be tap1 instead of being assigned by OpenVPN, again because of running a separate OpenVPN server. Even if you're not running a VPN server, this change shouldn't matter. The firewall scripts have been written to use tap1, so if you would rather use another device then remember to change those scripts where appropriate.

  • lladdr 00:FF:11:AA:BB:CC tells OpenVPN to assign the tap interface to have this MAC address, which can be useful for iptables firewall rules.

  • route-up and down run scripts to start and stop Transmission-daemon as required - these are needed here because they run with environment variables containing information about the connection, which is needed to correctly bind Transmission to the right IP address and port.

In my case, I had a server certificate from the VPN provider - which also has to be in the same directory as the config file.

sudo vim /opt/ibVPN/ibvpn.com.crt

Copy and paste this, or move it via SCP or SSHFS.

-----BEGIN CERTIFICATE-----
MIIDeDCCAuGgAwIBAgIJAMVKgpjMPUfxMA0GCSqGSIb3DQEBBQUAMIGFMQswCQYD
VQQGEwJVUzELMAkGA1UECBMCQ0ExFTATBgNVBAcTDFNhbkZyYW5jaXNjbzEVMBMG
A1UEChMMRm9ydC1GdW5zdG9uMRgwFgYDVQQDEw9Gb3J0LUZ1bnN0b24gQ0ExITAf
BgkqhkiG9w0BCQEWEm1lQG15aG9zdC5teWRvbWFpbjAeFw0xMDA3MjExOTU5MzVa
Fw0yMDA3MTgxOTU5MzVaMIGFMQswCQYDVQQGEwJVUzELMAkGA1UECBMCQ0ExFTAT
BgNVBAcTDFNhbkZyYW5jaXNjbzEVMBMGA1UEChMMRm9ydC1GdW5zdG9uMRgwFgYD
VQQDEw9Gb3J0LUZ1bnN0b24gQ0ExITAfBgkqhkiG9w0BCQEWEm1lQG15aG9zdC5t
eWRvbWFpbjCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAz23m3BXY5Asiw8Dx
T4F6feqsp+pIx6ivftTniyUCbSAxI1J1s1x75DzxmUpIwPu5xavzgPXgZr8FT81X
JGqF9km4AE95iddJawKx0wNgdTo7GximQq9rw0dsQIB5hZZQ9TJwHC3VOnmEic5A
OawKOCybMcRs8saLakZOgh7Xc+UCAwEAAaOB7TCB6jAdBgNVHQ4EFgQUeRhE2N4l
XwL4H1dbjkZ4ou6fj3AwgboGA1UdIwSBsjCBr4AUeRhE2N4lXwL4H1dbjkZ4ou6f
j3ChgYukgYgwgYUxCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJDQTEVMBMGA1UEBxMM
U2FuRnJhbmNpc2NvMRUwEwYDVQQKEwxGb3J0LUZ1bnN0b24xGDAWBgNVBAMTD0Zv
cnQtRnVuc3RvbiBDQTEhMB8GCSqGSIb3DQEJARYSbWVAbXlob3N0Lm15ZG9tYWlu
ggkAxUqCmMw9R/EwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQUFAAOBgQASt0pl
WzVseQLTNM8Mlgw4ZnGAv/x2xnijmMqrkE+F7pnaOicGpxgCfMKzjZuJu0TNJqF2
fibE7GhMdomD4dLFgIu8Wb5E7iQ1CSBEOGumRhK8qCsDzjr7WXUdhqA6Xvo+ylU6
DMzy0Wn3NNvfGC+qxOgybYCJwDnVPi0CEDSbzQ==
-----END CERTIFICATE-----

Obviously if you aren't using an ibVPN account, your certificate will be different.

Let's now make the password file:

sudo vim /opt/ibVPN/pass

The first line must be the full username, then the second line must be the password. This must be the only contents of this file.

you@address.com
myBIGstrongpassword1234567890

We also have to secure the permissions on this file, or OpenVPN won't start.

sudo chmod 400 pass

This will make the file read-only, and only for the owner (i.e. no other user can read it at all)

These commands will create the files to run at startup, and set them to be executable only by root.

sudo touch route-up.sh
sudo touch down.sh
sudo chmod 700 route-up.sh
sudo chmod 700 down.sh

At this point, it is probably a good idea to test if the VPN connection actually works. Start the connection with:

sudo openvpn --cd /opt/ibVPN --config config.ovpn

You will see warnings that the up and down external commands could not be run, but don't worry about that. If it works, you will see Initialization Sequence Completed on the terminal. Press Control+C to end the connection. If it doesn't work, you will have to investigate why not and fix it before continuing. I found that it sometimes it took a few goes to start working. Make sure your password file is correct. There are lots of great resources on the Internet about OpenVPN, so have a look around.

At this point, it's probably easiest to move on to getting Transmission up and running. Once you are sure that both the VPN and Transmission can run separately, they can be combined.

Installing and configuring Transmission

Install the required packages:

sudo apt-get install transmission-daemon

By default, Transmission will run automatically on boot. Since we will eventually be using OpenVPN to start Transmission, we want to disable this. To do so, edit the config file for Transmission-daemon

sudo vim /etc/default/transmission-daemon

And change the following line to read:

ENABLE_DAEMON=0

Now Transmission will not start on boot.

Let's now create a directory for the Transmission settings to reside in, and for the downloaded torrents to go into. This assumes you've already set up a disk of some sort, and it's mounted at /media/arm-disk/. For security purposes, the daemon will be run by its own user rather than as root or as "ubuntu". A new user is created by the installer for transmission-daemon, "debian-transmission". This user needs to own the folder that we create, and have read and write access to the storage location for the torrents being downloaded.

sudo mkdir /opt/transmission
sudo chown debian-transmission:debian-transmission /opt/transmission
sudo mkdir /media/arm-disk/torrents-complete
sudo chown debian-transmission:debian-transmission /media/arm-disk/torrents-complete
sudo mkdir /media/arm-disk/torrents-incomplete
sudo chown debian-transmission:debian-transmission /media/arm-disk/torrents-incomplete

Now we need to start transmission, just briefly, so that it creates the settings file we need:

sudo -u debian-transmission -g debian-transmission /usr/bin/transmission-daemon --config-dir /opt/transmission --foreground

This command starts transmission-daemon as the debian-transmission user, tells it to use the /opt/transmission directory for the settings files, and tells it to keep running in the foreground. Once it has run for a few seconds, press Control+C to end it. We can now edit the settings file.

sudo -u debian-transmission vim /opt/transmission/settings.json

We now need to change to following lines from their defaults to read:

"download-dir": "/media/arm-disk/torrents-complete",

"incomplete-dir": "/media/arm-disk/torrents-incomplete",

"incomplete-dir-enabled": true,

"rpc-whitelist": "127.0.0.1,192.168.1.*",

Save and exit (Escape, type :wq and press Enter)

The middle two edits will enable the use of the "incomplete" directory, separating your finished torrents from the unfinished ones. This isn't completely necessary, but I personally find it extremely useful. The last edit enables the web GUI to be accessed by any computer on the LAN (assuming your LAN subnet is 192.168.1.0, modify this if it is different).

It's now a good idea to run Transmission again, to see if it works and can actually download a torrent. We will use a web browser window to access the GUI and to add a torrent. First, let's allow access to the web GUI through the firewall from the LAN, then run transmission-daemon again.

sudo ufw allow in from 192.168.0.0/16 to any port 9091
sudo -u debian-transmission -g debian-transmission /usr/bin/transmission-daemon --config-dir /opt/transmission --foreground

Visit this URL in Firefox (or whichever browser you prefer): http://XXX.XXX.XXX.XXX:9091 , where XXX is replaced by the address of your server on the LAN (i.e. 192.168.1.10). Find a torrent to download, for example Big Buck Bunny in 1080p60hz. This is a free short film, legally available for free download. In the Transmission GUI, click the "Open Torrent" button, and paste this link (or any other torrent you like) into the first box. Then press "Upload". If Transmission is working correctly, the torrent will begin to download. If it does not, then you will need to work out why before continuing. There are lots of resources available on the Internet for using transmission-daemon. It could also be the torrent you chose isn't working, try a few others first.

Once the download is finished, press Control+C in the terminal window to stop transmission-daemon.

Configure binding Transmission to the VPN interface

Now let's make an Upstart script, which will be used to start Transmission when the VPN is ready.

sudo mv /etc/init/transmission-daemon.conf /etc/init/transmission-daemon.conf.bak

Don't worry if this complains, it's just to make a backup of the Upstart file, if one existed - it might not have. Let's open vim to edit the new one:

sudo vim /etc/init/transmission-daemon.conf

Paste this into the editor:

description "transmission-daemon, attached to OpenVPN tunnel tap1"

start on transmission-daemon-start stop on runlevel [!2345] or transmission-vpn-down

This includes the information from OpenVPN into this environment

export LOCAL_IP env PORT=51413

give time to send info to trackers

kill timeout 30

Run as unprivileged user

setuid debian-transmission setgid debian-transmission

Start transmission again if it stops for some reason

respawn

If transmission stops 5 times in a minute, give up trying to respawn it

respawn limit 5 60

exec /usr/bin/nice -15 /usr/bin/transmission-daemon --config-dir /opt/transmission --bind-address-ipv4 $LOCAL_IP --peerport $PORT --no-portmap --foreground

Save and close vim. (Escape, then type :wq). Again, open vim:

sudo vim /etc/init/transmission-up.conf

And paste this:

description "Script to create firewall and routing rules for transmission-daemon"

start on transmission-vpn-up

This includes the information from OpenVPN into this environment

export VPN_GATEWAY export LOCAL_IP env PORT=51413

task

script # Set up IP route, firewall rules # It doesn't matter if they already exist, they will be skipped /sbin/ip route add default via $VPN_GATEWAY dev tap1 table 200 /sbin/ip rule add from $LOCAL_IP table 200 /sbin/ip route flush cache /usr/sbin/ufw insert 1 reject out on eth0 from any port $PORT /usr/sbin/ufw insert 1 reject in on eth0 to any port $PORT /usr/sbin/ufw insert 1 deny in on tap1 to any /usr/sbin/ufw insert 1 allow in on tap1 to any port $PORT proto udp

# Start the actual transmission-daemon process, in a separate task so that unprivileged user/group can be set
/sbin/initctl emit transmission-daemon-start LOCAL_IP=$LOCAL_IP

end script

Again, save and close vim. (Escape, then type :wq). Finally:

sudo vim /etc/init/transmission-down.conf

Paste this:

description "Script to remove firewall rules for transmission-daemon"

start on runlevel [!2345] or stopping openvpn-transmission env PORT=51413

task

script # Take down IP route, firewall rules # It doesn't really matter if they don't get taken down, but this will be cleaner /usr/sbin/ufw delete reject out on eth0 from any port $PORT /usr/sbin/ufw delete reject in on eth0 to any port $PORT /usr/sbin/ufw delete deny in on tap1 to any /usr/sbin/ufw delete allow in on tap1 to any port $PORT proto udp

/sbin/ip route flush cache

end script

These scripts tell Upstart to listen for the "transmission-vpn-up" signal. The "transmission-up.conf" script then sets up the required routing rules to send traffic from the local VPN address via the VPN interface, and sets the firewall to allow in traffic from the VPN to the listening port for Transmission. Traffic directed to Transmission's listening port from the normal LAN interface is blocked. The "transmission-daemon.conf" script then starts transmission-daemon with the required settings to bind it to the VPN IP address. Note that this command will also ensure UPnP/NAT-PMP is disabled - see my note at the top about port forwarding. The "nice -15" sets Transmission to have a lower priority, which I found useful when using the lower spec'd BeagleBone - sometimes Transmission can hog resources, which slows the system down. At least with a low priority, more important system tasks can still run. The "transmission-down.conf" script will remove the firewall rules when the VPN is stopped. Three different scripts are used so that transmission-daemon can be run as an unprivileged user, but the firewall rules can be run as root.

Now let's go back to the OpenVPN settings, and edit the "route-up" and "down" scripts to trigger starting and stopping our Transmission script.

sudo vim /opt/ibVPN/route-up.sh

Paste this into vim:

#! /bin/bash

/sbin/initctl emit transmission-vpn-up VPN_GATEWAY=$route_vpn_gateway LOCAL_IP=$ifconfig_local

All this script does is say to Upstart that transmission-daemon should start, and gives it the information it needs to attach to the VPN connection.

sudo vim /opt/ibVPN/down.sh

Again, more pasting:

#! /bin/bash

/sbin/initctl emit transmission-vpn-down

This script is even more simple - it signals for transmission-daemon to stop.

At this point, it is probably a good idea to make sure that the owner of the entire VPN config folder is the root user - since these scripts run as root, anyone who could change them could run anything they wanted to as the root user.

sudo chown root:root -R /opt/ibVPN
sudo chmod 700 -R /opt/ibVPN
sudo chmod 400 /opt/ibVPN/pass

This now means that only the root user can modify or view the VPN connection settings.

OK, we're nearly done! Let's test if our setup is working so far:

sudo openvpn --cd /opt/ibVPN --config config.ovpn

Connect again to the Transmission web GUI, and resume the existing torrent or add a new one. It should be able to download, maybe after a few minutes of waiting for peers. A nifty way I found of testing whether or not it is working is to look at iftop. Install iftop, and run:

sudo apt-get install iftop
sudo iftop -i tap1

This screen will be showing all connections running through the VPN. If your torrent is downloading and is correctly using the VPN, there will be lots of IP addresses and host names here. Also look at iftop for the LAN connection:

sudo iftop -i eth0

Here you should see a large amount of traffic to a single IP address, being the VPN server, and then only minimal traffic to other LAN devices - assuming that you aren't running other services on your BeagleBone.

You can confirm that the VPN is working by following these instructions.
This site lets you download a torrent to see the IP address other peers use to connect to you - if everything is working this will be the VPN IP address and not your own WAN IP address.

If you are experiencing issues, you can see the Upstart error log by doing:

sudo tail -f /var/log/upstart/transmission-daemon.log

In a separate terminal/SSH window, try running the tail command while starting the VPN connection as above and look for any error messages. Hopefully you can resolve the issue from seeing the error messages, if not have a dig around on the Internet, or post a comment.

Configure it all to start automatically

If you are happy with manually issuing the command to start the OpenVPN tunnel, or you want to do it with your own script, then you are done. But I wanted it to start on boot, so I made another Upstart script to launch OpenVPN.

sudo vim /etc/init/openvpn-transmission.conf

This is the last thing we have to paste!

description "OpenVPN client, with attached transmission-daemon"

start on started networking stop on runlevel [!2345] or stopped networking

Give time for Transmission to send info to trackers, wait for graceful close

kill timeout 45

Start the OpenVPN tunnel again if it stops for some reason

respawn

If it stops 5 times in a minute, give up trying to respawn it

respawn limit 5 60

exec openvpn --cd /opt/ibVPN --config config.ovpn

post-stop script # Pause for a few seconds, before exiting /bin/sleep 3s end script

All this does is wait for the system to signal that the network is ready, and then it will start the OpenVPN tunnel - which will in turn start Transmission. When the system is turned off, or if networking is shut down for some reason, Upstart will remove the firewall rules and close transmission-daemon. Simple! This will continue to work after a reboot too, so now you're all set.

To interact with Transmission, use the web GUI as we did during the setup phase. It is also possible to make the GUI accessible over the Internet, by setting up port forwarding. There are lots of tutorials on how to do this, so I won't repeat it here.

As for getting the completed downloads off the BeagleBone, I'm using NFS. I can get speeds of about 8 MB/s copying over the LAN from the BeagleBone to my desktop computer - which is pretty good for such a low-powered device. Ubuntu provides some handy information for setting this up.

seanlano
  • 2,986
  • 3
  • 28
  • 44
  • Wow! How long did you spend looking for all this stuff? – Ismael Miguel Feb 10 '15 at 10:45
  • Haha, quite a while. I'd done it once before on a DD-WRT router, then when I was doing i again for the BeagleBone I thought I'd write this up so I don't forget how to do it. :D – seanlano Feb 10 '15 at 10:59
  • This is valuable information. Not only for you but for someone else. I've made this account here just to say that! – Ismael Miguel Feb 10 '15 at 11:02
  • I've noticed recently that when I set Transmission to download overnight, CPU usage goes to 100% after a few hours, and then the usage of other processes stays high for quite a while after pausing. I've also got Syncthing running on the same system, and I think they fight for resources or something like that. I'm not sure how Transmission could cause Syncthing to have high CPU usage, but it appears that it does. I'm still investigating. – seanlano Feb 13 '15 at 22:20
  • 4 years ago I had similar problems, but it was an old version 'fighting' against Opera 12. I've downloaded Transmission from the Debian repositories and installed on puppy linux 4.3.1. I've always assumed it was my CPU crapping out, since the computer was incredibly weak. – Ismael Miguel Feb 13 '15 at 23:16
  • I once had Transmission running on a DD-WRT router, with a 400 MHz MIPS processor - and I don't remember it being too bad. I think there might be a bug in the ARM build. – seanlano Feb 16 '15 at 00:51
  • Sadly, it wasn't on an ARM CPU. It was an Intel Centrino. Which one exactly, I don't remember. But it was single-core. Transmission crashed A OT, using almost 100% of the CPU. Are you using the most recent build? I was, but it was 4 years ago. And it was a Debian-compatible distribution (to which I had to install the dependencies manually). If you really believe it has a bug, try an older version (don't use it for anything else other than testing!). – Ismael Miguel Feb 16 '15 at 09:30
  • @IsmaelMiguel, I'm using the most recent ARMHF build in the official Ubuntu repos for 14.04. I might try an older version and see if it makes a difference. Also my earlier mention of Syncthing having issues seems to just be related to the overload of the processor - after I kill Transmission the system returns to normal after about 10 minutes. Hmmm...... :/ – seanlano Feb 16 '15 at 10:56
  • ARM CPUs are quite weak. You probably need to tweak the number of acceptable connections. And limiting some other stuff. Also, check the RAM usage. It might be trying to swap and (since the CPU is slower than a x86) that may be causing a disaster everywhere. Also, you may try to limit the process' CPU usage with the nice command (if I'm not mistaken). – Ismael Miguel Feb 16 '15 at 10:59
  • Yeah I've definitely noticed how slow ARM is compared to even a low-powered x86 CPU. It does use less than 5 watts though, so it's fair enough really.

    I do use nice, with 15 as the niceness. It seems not to matter, it still brings the system to its knees. But I'll try and play with the settings and see what I can do. According to htop the RAM usage isn't worse than about 80%, and there is no swap space at all. I might try adding some swap to see what happens.

    – seanlano Feb 16 '15 at 11:03
  • You should have always some swap. Even if it completely empty. I don't think that swap will help a lot, but it is a great idea to keep it around. Have you tried to check your disk for damaged sectors? Can you try to install Debian and try to configure the same way? I've noticed that Debian is A LOT lighter. Try to find the LXDE version (I know, I know. It isn't as pretty as Unity). Use that one. I had fantastic results with it running on VirtualBox. – Ismael Miguel Feb 16 '15 at 11:23
  • I'm running this box completely headless, so Unity doesn't bother me. ;) Alright so my plan of action to work on this: 0) Add some swap space 1) Change some Transmission parameters to see if it improves 2) Try different versions of Transmission 3) Try using Debian instead of Ubuntu. After that I give up. :P I'll let you know how I get on. – seanlano Feb 16 '15 at 23:24
  • In my opinion, you should try with Debian first. Then you can mess with all the other stuff. But I get your reasoning. My argument against your decision is that Debian is so easy to configure and get up running that and so much faster (when using LXDE) than Ubuntu (with or without Unity) and jumping all the middle stuff to this step may be beneficial. The argument against is that I don't know exactly what is going on. And messing with Transmission is easier and less cumbersome and dangerous than installing another OS. But I'm curious about the outcome of your attempts! – Ismael Miguel Feb 16 '15 at 23:45
  • 1
    You should also read this: http://unix.stackexchange.com/questions/88693/why-is-swappiness-set-to-60-by-default/88820#88820 (It's a great answer.) This will help you, I'm sure of it. – Ismael Miguel Feb 17 '15 at 00:03
  • I'll give it a go then, if I can figure out how to make an image of the BeagleBone onboard disk so I can restore this Ubuntu setup if I want to. Since Ubuntu is derived from Debian, I'm imagining that the installation steps I made above will be identical - except for the Upstart scripts I suppose. They might be a bit of a pain. – seanlano Feb 17 '15 at 03:39
  • You can make an entire copy of your disk using Clonezilla. You need to have somewhere to store it. They have pretty nice examples, very well explained (I was able to copy a few disks, so, it must be extremelly well explained!). Their website (http://clonezilla.org/) has the iso files to download and run from a CD/DVD or usb. – Ismael Miguel Feb 17 '15 at 09:09
  • Alright, so I've tried a few different versions of Transmission, back down to 2.51. I also added swap space. The issue persists. :/ Next I might try using Raspbian on the Beaglebone, to see if that helps. – seanlano Mar 03 '15 at 09:41
  • That is so weird in so many levels... Did you compiled the source-code or you installed from the package manager? – Ismael Miguel Mar 03 '15 at 09:50
  • I just used the packages from the repository, I didn't do any compiling. I still haven't had time to mess around with Debian yet, but I hope to do so soon. Needless to say, the issue hasn't magically resolved itself. :P – seanlano Mar 10 '15 at 23:23
  • You really should look into a way to compile the sourcecode. You can try to look into bittorrent or similar. If you don't have any alternative, try to use WINE with the Windows version of a client. In case everything fails, install Opera 12.17 and pray that the torrent client in it works. – Ismael Miguel Mar 10 '15 at 23:36
  • 3
    I've just realised, after setting my DNS server to use OpenDNS and looking through the stats, that this config leaks DNS through the normal WAN connection. I'll investigate further to see if I can fix this. I'm going to keep running anyway, since the connection itself is through the VPN - but it's not ideal. – seanlano Feb 22 '16 at 01:25
  • 1
    @seanlano Thanks for bringing this to our attention. Let us know if/when you find a fix. – P A N Mar 07 '16 at 19:08
8

Just got this working using SystemD so I thought I'd share. I have placed all of my scripts, configs, and certificates in the same directory which I will refer to as /etc/openvpn/myprovider

OpenVPN config

This depends on your specific VPN, but one difference from @seanlano's config is that I only use a route-up script. So the things you need in addition to your working provided config, are these lines:

route-noexec
route-up "/etc/openvpn/myprovider/transmission-route-up.sh"

Where you place the transmission-route-up.sh script wherever you like. Note the absence of a down script. (My VPN was already using a custom down script so it would have conflicted anyway).

/etc/openvpn/myprovider/transmission-route-up.sh:

#!/bin/sh

# Print environment variables for transmission's benefit
printenv > /etc/openvpn/myprovider/vpn.env


# Set up VPN routes
ip route add default via $route_vpn_gateway dev $dev table 10

ip rule add from $ifconfig_local/32 table 10
ip rule add to $route_vpn_gateway/32 table 10

ip route flush cache


# Add firewall rules
iptables -A INPUT -i $dev -p udp --dport 24328 -j ACCEPT
iptables -A INPUT -i $dev -p tcp --dport 24328 -j ACCEPT

iptables -A OUTPUT -o $dev -p udp --sport 24328 -j ACCEPT
iptables -A OUTPUT -o $dev -p tcp --sport 24328 -j ACCEPT

The first line, the printenv, is important. Place it wherever you like, it is used in the SystemD service later. I place it in the same directory as my vpn config.

Replace 24328 with whatever port your transmission-daemon should listen on. I use iptables (using Debian), so you can probably replace those lines with the ufw lines from @seanlano's config.

SystemD VPN service

This is the service which auto starts the VPN for us. Verify that the path to openvpn is correct on your machine, and that the path to the config file is correct as well. You must specify full paths in SystemD services.

/etc/systemd/system/my-vpn.service:

[Unit]
Description=VPN connection
After=network.target

[Service]
Type=forking
PIDFile=/var/run/openvpn/vpn.pid
ExecStart=/usr/sbin/openvpn --cd /etc/openvpn/myprovider --config /etc/openvpn/myprovider/myconfig.ovpn --daemon --writepid /var/run/openvpn/vpn.pid

[Install]
WantedBy=multi-user.target

Enable the VPN service with:

systemctl enable my-vpn.service

And test it with:

systemctl start my-vpn.service
systemctl status my-vpn.service

If it's started/running, you're good.

SystemD transmission-daemon.service

This script requires the vpn-service, so if the vpn goes down, transmission-daemon also goes down. This is handy if the vpn is restarted, and you get a new IP-address, because transmission will need to restart and re-bind then, which should be handled automatically. Note that we make use of the environment variables we printed in the route-up script earlier.

/etc/systemd/system/transmission-daemon.service:

[Unit]
Description=Transmission BitTorrent Daemon Under VPN
After=network.target my-vpn.service
Requires=my-vpn.service

[Service]
User=debian-transmission
Type=notify
EnvironmentFile=/etc/openvpn/vpn.env
ExecStart=/usr/bin/transmission-daemon -f --log-error --bind-address-ipv4 $ifconfig_local --rpc-bind-address 0.0.0.0 --no-portmap
ExecReload=/bin/kill -s HUP $MAINPID

[Install]
WantedBy=multi-user.target

Enable it

systemctl enable transmission-daemon.service

And start it

systemctl start transmission-daemon.service

When you reboot, it should all start automatically (in order!). Note that using Type=simple in the vpn service causes some problems for the timing of script ordering, hence I recommend using forking instead.

You can specify an actual ip-address for the rpc-bind-address if you want to be more restrictive (this is the web GUI listening address, which should not be your VPN-ip). And if you want to run transmission with nice, just change the ExecStart line and add /usr/bin/nice -n15 to the beginning.

Handling address changes

One thing I've noted over time is that if the vpn-connection for some reason gets a new ip-address, transmission will still be bound to the old address and stop working. And simply doing systemctl restart transmission-daemon.servicedoesn't cut it. It needs to stop fully, and then start fresh.

No idea why, but for that reason I have added the following lines to my root crontab (sudo crontab -e):

# m h  dom mon dow   command
0 6 * * * /bin/systemctl stop my-vpn.service; /bin/systemctl start my-vpn.service
1 6 * * * /bin/systemctl stop transmission-daemon.service; /bin/systemctl start transmission-daemon.service
  • Just out of interest, is this also running on a BeagleBone? If so, do you see performance issues with Transmission? Also, great write-up. :) – seanlano May 12 '15 at 09:53
  • Ah no. It's running on my normal desktop machine and I have noticed no issues there. – Jonas Kalderstam May 12 '15 at 09:56
  • Fair enough. Works fine for me on an Intel machine, I was hoping I could make a cheap torrent box with an ARM processor - but apparently it is not to be. – seanlano May 13 '15 at 12:17
  • Check out rtorrent. It is very performant – Jonas Kalderstam May 13 '15 at 13:13
  • Thanks, I will. Other things run fine on the ARM box, so maybe rtorrent will work properly. – seanlano May 16 '15 at 03:09
  • I'm now using a 15.04 box, and so your systemd config is coming in handy! I've got a quick question, in your systemd my-vpn.service you have Type=forking and then start OpenVPN with /usr/sbin/openvpn --daemon and use the PID file etc. How come you didn't leave out the Type=forking directive and the --daemon flag and let systemd manage it in the foreground? I'm pretty sure that Upstart prefers foreground processes, but I don't have much experience with systemd yet. – seanlano Sep 11 '15 at 01:27
  • No specific reason. I think it's probably what I saw in some other openvpn-service, so just a copy-paste thing. If it works without --daemon, then go for it :) – Jonas Kalderstam Sep 11 '15 at 09:10
  • I ran into a problem where SystemD would start transmission before openvpn had written the environment file in route-up.sh, and so the transmission service would fail. To fix, I added a sleep to the transmission service definition with ExecStartPre=/bin/sleep 10, so that it will give some time for openvpn to fully complete its setup. – gapple Nov 03 '15 at 05:36
  • @JonasKalderstam Thanks for your write-up. I tried following you (also running Debian), but when trying to sudo systemctl start my-vpn.service I get the error: Active: failed (Result: exit-code) and ... (code=exited, status=1/FAILURE). Any idea why? – P A N Dec 02 '15 at 12:59
  • @Winterflags Nope, it's still going strong on my machine. What do you see from sudo systemctl status my-vpn.service -l and sudo journalctl -u my-vpn.service ? – Jonas Kalderstam Dec 02 '15 at 13:05
  • Thanks for your reply! It says Options error: In [CMD-LINE]:1: Error opening configuration file:. Strangely, because I'm pretty sure I've entered the right directory: ExecStart=/usr/sbin/openvpn --daemon --writepid /var/run/openvpn/vpn-transmission.pid /etc/openvpn --config vpn.conf – P A N Dec 02 '15 at 13:10
  • @Winterflags the problem is --config vpn.conf, you are not specifying the full path to the config file. I'll update my example code above to make this clear. SystemD always requires full paths – Jonas Kalderstam Dec 02 '15 at 13:14
  • Ah, thanks. I did see your remark about that, but didn't realise it tied in to the --config argument. :) – P A N Dec 02 '15 at 13:16
  • @JonasKalderstam Sorry, now it says `Failed to start VPN connection". The log doesn't give any more information than that. The service enters a failed state, so no .pid is written, etc. – P A N Dec 02 '15 at 13:44
  • @winterflags that seems related to your vpn settings. Make sure you can start a vpn connection manually in the terminal before shoving it into the service file. – Jonas Kalderstam Dec 02 '15 at 13:47
  • Thanks for the update! I'm having an issue now where the current IP of the VPN is saved to ifconfig_local= in vpn.env, but the IP isn't passed on to settings.json. It's only there once I restart. I think the reason is that, when I check the timestamps, settings.json is actually written by the daemon a few seconds before vpn.env is updated. So the next time I connect, the IP will be there. But this is a problem because I'm given a new IP each time I connect to the VPN, effectively "lagging" behind by one IP all the time in settings.json. Any idea how to fix this? – P A N Dec 02 '15 at 19:10
  • @Winterflags Yes possibly. I have experienced some problems with simple, with Transmission not having the right ip. "loaded" and "inactive" sounds like you haven't started the transmission service. Note that manually starting the vpn service will not automatically start transmission, that only happens automatically on boot. – Jonas Kalderstam Dec 13 '15 at 21:39
  • @JonasKalderstam Okay, got it working now :) I added a .timer script in systemd with OnBootSec=20 that then starts the Transmission daemon. Guide here. That allows settings.json to get the current IP from vpn.env. It works with simple for the OpenVPN service. Many thanks! – P A N Dec 13 '15 at 22:15
  • Is there reason to believe that this configuration leaks DNS queries similarly to what @seanlano updated his answer with? – P A N Apr 09 '16 at 18:32
  • @JonasKalderstam I believe there might be some problems with leaks. See my question here. – P A N Apr 10 '16 at 11:03
  • instead of the "crontab" i think it would be more efficient to stop the transmission service in an openvpn "route-pre-down" script, and start transmission in an openvpn "route-up" script... – Motsel Nov 23 '16 at 21:58
3

I noticed you mentioned that Transmission does not goes through the VPN for UPnP/NAT-PMP. I noticed this as well and created a patch for Transmission so it honors the bind-address-ipv4 setting for UPnP. NAT-PMP is a bit harder to implement since you need to determine the default gateway. UPnP is the main one that is being used these days, though, so it is probably good enough. I logged this as a bug on the trac.transmissionbt site and provided the patch. Hopefully it will be incorporated in a future release. https://trac.transmissionbt.com/ticket/5990

Another option for right now if you don't want to recompile is to manually run upnpc from the miniupnpc package. E.g.

sudo apt-get install miniupnpc
upnpc -m 10.10.10.51 -a 10.10.10.51 51515 51515 TCP
upnpc -m 10.10.10.51 -a 10.10.10.51 51515 51515 UDP

Where 10.10.10.51 is your VPN IP and 51515 is your requested TCP/UDP port.

I'm not sure how long the forwarding is good for. Also you might want to use the '-d' option to remove your port when disconnecting. I found that if I don't, I can't get I same port again if I relogin into the VPN.

Cheers

falk0069
  • 31
  • 1
  • I spent ages trying to find a solution like this, I wish I'd found miniupnpc ! And hopefully the patch does get merged and this issue will be fixed forever. In the meantime I'll definitely be trying to use your handy tip. – seanlano Sep 10 '15 at 01:53
0

On top what its already written regarding SystemD service... it would make more sense to bound VPN service with Transmission serivce - so when You will restart VPN then Transmission should also be restarted... to achieve this You need to edit VPN serice file

vi /etc/systemd/system/my-vpn.service

and add those lines:

PartOf=transmission-daemon
ExecStartPost=/bin/sleep 30

Into the [Service] section.

PartOf will make one direction dependency - If VPN will be restarted then restart metioned those service as well. (documentation)

In my case - VPN needed few seconds more to setup and immediate start of Transmission caused that Transmission daemon was using "old" env file - therefore I have added extra "wait" time 30s (ExecStartPost=/bin/sleep 30) after VPN has started just to make sure.

Im in the testing phase right now - so this is not yet "home production server" yes - so I often yet put on sleep my PC. after that my VPN connection does not work. So I didnt yet make it but it would be nice to have some kind of watchdog functionality to test if VPN connection is still alive - but this is on my TO DO list yet...

Additionally, to test if Your setup actually works then You may use this service torguard.net where You can "download" torrent file and open it in Your remote Transmission and verify what error / comment is returned from Tracker - it should return Your VPN/masked IP and on same page You can track current connections to check if this works at all.

0

New approach in 2022: Network Namespaces

In the years since I first attempted this, there's been some developments that make setting up Transmission to run over a VPN easier and more reliable – using a "Network Namespace". This doesn't just apply to Transmission, it could be for any systemd service. It no longer relies on the application correctly binding to the appropriate network interface, instead systemd will force all network traffic to use the configured namespace – which in our case will mean sending it though the VPN.


1. Configure networking

There's many ways that networking might be configured, in my case I was already using Netplan to create a bridge. It's probably not necessary to create one if you aren't also using it for other reasons (instead use the NAT option), but for reference here is my Netplan config which I'm using in this example. You'll need to adjust as appropriate, or configure the network interfaces with another tool of your choosing.

Example Netplan config:

network:
  version: 2
  renderer: networkd
  ethernets:
    enp1s0:
      dhcp4: no
      dhcp6: no
  bridges:
    br0:
      interfaces: [enp1s0]
      dhcp4: no
      dhcp6: yes
      dhcp6-overrides:
       use-dns: yes
       use-ntp: yes
       send-hostname: yes
       use-hostname: no
      addresses:
        - 192.168.64.200/24
        - "aaaa:bbbb:cccc::200:1/64"
      ipv6-privacy: yes
      gateway4: 192.168.64.1

2. Install and configure systemd-named-netns scripts

Although systemd supports network namespaces, it doesn't have much in the way of configuration for them. Fortunately, a helpful fella called James Swineson has made a set of scripts which create systemd services for various network namespace configurations.

Download the repository:

git clone https://github.com/Jamesits/systemd-named-netns.git

Install the scripts:

cd systemd-named-netns/
sudo make install

3. Configure systemd-named-netns

The exact configuration you need will depend on your network setup. I'm using a bridge, but a NAT option is also available. See the wiki page for more information.

The rest of this guide assumes that you're using a bridge. I'm using the name torrentvpn for the namespace, it will come up in a few places. If you decide to use a different name, make sure it only contains alphanumeric characters and is not longer than 12 characters.

Create a resolv.conf file for the DNS settings to use inside the network namespace:

sudo mkdir -p /etc/netns/torrentvpn/
sudo touch /etc/netns/torrentvpn/resolv.conf

Then edit the file /etc/netns/torrentvpn/resolv.conf to this:

nameserver 8.8.8.8

This will use Google's DNS service for anything that runs inside the network namespace, feel free to use another if you prefer – NextDNS is a good alternative.

Now let's configure the namespace bridge, edit the file /etc/default/netns-torrentvpn to this:

# Bridge name
BRIDGE=br0

If you need DHCP

DHCPV4=1

Set a static MAC, helpful with DHCP

MACADDR=02:00:00:aa:bb:01

Device name outside netns

DEVNAME_OUTSIDE=veth0

Device name inside netns

DEVNAME_INSIDE=veth1

At this point we can test our network namespace setup, start the namespace with this command:

sudo systemctl start netns-bridge@torrentvpn.service
sudo systemctl enable netns-bridge@torrentvpn.service

Then try to ping something from inside the namespace, and make sure it works:

sudo chnetns torrentvpn ping google.com

4. Set up OpenVPN

There's a crazy number of VPN service providers out there, so the steps might be slightly different for you. Ideally you should confirm you can get an OpenVPN tunnel set up using the config files from your provider, possibly using a graphical interface first if that's easier. In theory it doesn't even have to be OpenVPN, it can be any VPN that you can get running through systemd.

I have an account with ProtonVPN, who provide OpenVPN configuration files which have the necessary certificates and keys embedded inline. The config file is saved at /etc/openvpn/client/protonvpn.conf and I've modified it to have the username and password read from the file at /etc/openvpn/client/protonvpn.pass (with the auth-user-pass config option). You'll need to adapt this to suit your provider.

The OpenVPN package provides systemd scripts for managing a client connection, although we want to add an extra couple of lines so that our connection uses the network namespace. Run this command:

sudo systemctl edit openvpn-client@protonvpn.service

and add the following lines:

[Unit]
BindsTo=netns@torrentvpn.service netns-bridge@torrentvpn.service
After=netns@torrentvpn.service netns-bridge@torrentvpn.service
JoinsNamespaceOf=netns@torrentvpn.service

[Service] PrivateNetwork=yes ExecStartPre=/sbin/sysctl net.ipv6.conf.all.disable_ipv6=1

This creates a "drop-in" override file at /etc/systemd/system/openvpn-client@protonvpn.service.d/override.conf, which lets us add our extra settings without needing to edit the config from the package maintainer. It also disables IPv6 inside the namespace, since my VPN provider doesn't support it and I don't want to accidentally end up using my non-VPN Internet connection.

Restart the systemctl daemon, then try to start the VPN:

sudo systemctl daemon-reload
sudo systemctl start openvpn-client@protonvpn.service
sudo systemctl enable openvpn-client@protonvpn.service

Test again with a ping through the namespace, this time the response time should be slower than before because of the extra distance the packets now have to travel to reach the VPN endpoint:

sudo chnetns torrentvpn ping google.com

5. Set up Transmission Daemon

There's lots of information about configuring Transmission, and you might have different desires, so read the documentation. I'll quickly show the main steps here.

Install Transmission:

sudo apt install transmission-daemon

Stop the daemon (systemd seems to start it after being installed)

sudo systemctl stop transmission-daemon.service

Edit the configuration file at /var/lib/transmission-daemon/.config/transmission-daemon/settings.json. In particular, you'll probably want to change download-dir to somewhere with sufficient storage, and also allow access from your LAN in rpc-whitelist (for me this meant adding 192.168.64.*). You will also need to set a password through rpc-password to log into the web UI.

Don't forget to set the correct permissions for your downloads directory:

sudo chown debian-transmission:debian-transmission /home/torrents/

6. Set Transmission to use the VPN

Similarly to how we edited the systemd config for OpenVPN with an override, we will do the same with Transmission:

sudo systemctl edit transmission-daemon.service

Add the following lines, and save:

[Unit]
BindsTo=netns@torrentvpn.service netns-bridge@torrentvpn.service
After=netns@torrentvpn.service netns-bridge@torrentvpn.service openvpn-client@protonvpn.service
Requires=openvpn-client@protonvpn.service
JoinsNamespaceOf=netns@torrentvpn.service

[Service] PrivateNetwork=yes

Reload systemd, then start the service:

sudo systemctl daemon-reload
sudo systemctl start transmission-daemon.service
sudo systemctl reenable transmission-daemon.service

Because of the namespace, Transmission's web UI won't be accessible from the IP of the host machine, but rather from the IP of the virtual device inside the namespace which is attached to the bridge we set up. To find that IP address, run:

sudo chnetns torrentvpn ip ad

and find the address of the veth device – for me it was 192.168.64.46. The Transmission UI is then accessible at http://192.168.64.46:9091 , using the username and password you set in the configuration file.

7. Testing it out

Everything should all be up and running now. The best way I've found to confirm that the torrents really do use the VPN to download is to use the handy checker that Torguard provide (thanks to @lemonek for introducing me to this!) – it gives you a special torrent to download, and shows which IP addresses attempted to share it. Compare the IP that shows up with your Internet IP, and make sure it is not the same. You can also check the IP seen by servers for anything using the VPN by running:

sudo chnetns torrentvpn curl http://ip.42.pl/raw

This will show the IP address seen by the server at ip.42.pl, which should be the same IP shown by the Torguard tool.

Weird behaviour in Ubuntu 18.04

Frustratingly, I found that on reboot the network namespace setup seemed to play up slightly on Ubuntu 18.04 (but not on 20.04), leaving me unable to test out shell commands inside the namespace with the chnetns command. Strangely though the namespace worked fine for services within systemd jobs, Transmission was still running just fine.

I tried a bunch of things but couldn't figure it out, but I did at least realise that by stopping and restarting everything it could all be made to work:

sudo systemctl stop netns@torrentvpn.service
sudo systemctl start transmission-daemon.service
seanlano
  • 2,986
  • 3
  • 28
  • 44