Skip to main content

Force an application to use VPN, using iptables in Linux

Enforcing an application, for example a torrent client like Transmission, to always use the VPN interface or any particular network interface for that matter, is trivially simple using iptables on Debian, Ubuntu or any other GNU/Linux distro.
Personally, I am running Debian Sid on the Raspberry Pi. Occasionally I use it for downloading files ( legal stuff, seriously, believe me :D  ) using Transmission Bittorrent client over a VPN connection. Sometimes it happens that the VPN connection fails and doesn't reconnect for whatever reason and Transmission continues pulling stuff directly over my internet connection, which I would like to avoid. Fortunately it is very straightforward to enforce rules based on application owner UID. Transmission runs under the owner debian-transmission in Debian (use htop to check this) and the following two lines of iptables ensures that any process with owner having UID, debian-transmission, will not use any other network interface apart from the OpenVPN tunnel interface tun0

pi@sam-berry ~ $ sudo iptables -A OUTPUT -m owner --uid-owner debian-transmission -d 192.168.0.100 -j ACCEPT
pi@sam-berry ~ $ sudo iptables -A OUTPUT -m owner --uid-owner debian-transmission \! -o tun0 -j REJECT

The first line ensures that, my Mac-mini having IP address 192.168.0.100 on the lan, can always access the web interface of transmission. The second line makes sure, no outgoing traffic can leave via anything other that tun0. 
Peace of mind restored, thanks to iptables.

Comments

Unknown said…
I am trying to accomplish the very same thing in Ubuntu 12.04 and this seems like a very simple solution.

Unfortunately, issuing this command closes Transmission's listening TCP port and also prevents Chromium from connecting.

I'd appreciate any advice you might have!

Andy
Sambit said…
That's a bit strange.

The rule should only apply to processes with owner "debian-transmission".

You can list the iptables rules using

sudo iptables -L

and check whether the rule was created successfully.
Unknown said…
Thank you, that was very helpful.
Also I unblocked my whole local network with
iptables -A OUTPUT -m owner --uid-owner torrent -d 192.168.178.0/24 -j ACCEPT
Whitaker said…
Hey all, I'm trying to force Transmission to use VPN only on Debian Wheezy but something seems to be different. Here is what I get when trying the following:

root@debian:/etc# iptables -A OUTPUT -m owner --uid-owner debian-transmission \! -o tun0 -j REJECT
iptables v1.4.14: owner: Bad value for "--uid-owner" option: "debian-transmission"
Try `iptables -h' or 'iptables --help' for more information.

Any ideas?

Thanks!!
Whitaker said…
Hey all, I'm trying to force Transmission to use VPN only on Debian Wheezy but something seems to be different. Here is what I get when trying the following:

root@debian:/etc# iptables -A OUTPUT -m owner --uid-owner debian-transmission \! -o tun0 -j REJECT
iptables v1.4.14: owner: Bad value for "--uid-owner" option: "debian-transmission"
Try `iptables -h' or 'iptables --help' for more information.

Any ideas?

Thanks!!
Sambit said…
Hi McRae,

Seems like for some reason, iptables is failing to perform a username lookup.
Manually find out the numeric uid of debian-transmission from the /etc/passwd file (should be the third field in the row).
Then try the iptables command, replacing "debian-transmission" with its equivalent numeric userid.
Hope it helps.
Whitaker said…
Thanks for the reply Sambit! When I look at the /etc/passwd file it contains no mention of "trans", but I can post the file in its entirety if that will help. Using the following command, would it be --uid-owner 1000?

root@debian:/home/jwhitakermcrae# ps aux | grep trans
1000 26718 2.4 0.1 437028 21376 ? Sl 10:48 0:00 transmission-gtk
root 26727 0.0 0.0 7828 880 pts/1 S+ 10:49 0:00 grep trans

Thanks for the help!!
Chris said…
Hi,

when adding both rules to my system I get no connection anymore. I have forwarded one Port from my VPN-ISP (AirVPN) and set the same port to my transmission. Transmission says that the port is "closed". Also it seems not to be able to connect to the tracker. It just gets the message "Announce Error - Could not connect to tracker."
Any suggestions whats going wrong here?

I am using Ubuntu 12.04.4 LTS.
Chris said…
This comment has been removed by a blog administrator.

Popular posts from this blog

Making inactve USB Hard Disk spin down automatically in Linux.

I have a 400GB Seagate IDE HDD connected to Mars, our hostel's file-server using an USB enclosure. The USB enclosure is a cheap "Made in China" product. Consequently it has some special "features". One such notable "feature" is that the disk is kept spinning by the controller even if there has been no disk I/O for a long time. I have three other USB disks connected to the same machine, a 1TB Seagate FreeAgent Desk External Drive, a 500GB Maxtor Basics External Drive and a 2.5" 60GB Fujitsu SATA Disk inside a Transcend USB enclosure. All of these spin down themselves if there has been no I/O for sometime. Keeping the hard disk spinning unnecessarily for ever, not only wastes power but also overheats the drive, thereby reducing its life. I tried noflushd, which is supposed to force idle hard disks to spin down, but found it to be of no help. USB enclosure generally work by performing an SCSI emulation over USB. sdparm is an utility which can be use...

Rendering LaTeX in Blogger.

Rendering LaTeX in Blogger is pretty easy thanks to the JavaScript LaTeX equation render engine from http://www.yourequations.com . To enable LaTeX rendering go to the Blogger Dashboard --> Layout --> Edit HTML . Then add the line <script> type="text/javascript" src="http://tex.yourequations.com/"></script> <script type="text/javascript" src="http://tex.yourequations.com/"></script> just before <body/> . Half the job is now done. Then, for example to render: \int_{0}^{\pi}\frac{x^{4}\left(1-x\right)^{4}}{1+x^{2}}dx =\frac{22}{7}-\pi Use the code: <pre lang="eq.latex"> \int_{0}^{1}\frac{x^{4}\left(1-x\right)^{4}}{1+x^{2}}dx =\frac{22}{7}-\pi </pre> The LaTeX code will now be displayed as: \int_{0}^{1}\frac{x^{4}\left(1-x\right)^{4}}{1+x^{2}}dx=\frac{22}{7}-\pi Ofcourse Javascript needs to be enabled in the Browser for the renderer to work.