Routing unmodified Virtual Machines through the TOR network

So far I had three different TOR setups:

  • A browser (Firefox) using a local HTTP proxy (Privoxy) which uses a local TOR client through SOCKS.
  • tsocks/torify to make non-SOCKS-aware-applications work through TOR.
  • A virtual machine (VM) where some applications are configured to use the local HTTP proxy and/or TOR client.

Each of these setups has different disadvantages and neither fits my requirements:

  • In the browser approach I had to turn off all plugins (Java, Flash, ..) and Javascript so they can not leak information about the local system. Unfortunately this breaks many websites nowadays.
  • The tsocks/torify approach works for most applications but they may leak information about the local system themselves. Anyway there is a small risk of just forgetting to type the “torify” in front of the command I want to execute which I really do not want to happen.
  • The VM approach is like putting the two previous approaches into a VM. So the risk of leaking local information is reduced to the VM. Anyway I have to make applications running within the VM explicitely use the TOR network. Besides I want to take care that no other traffic but TOR is going out of the VM which means I have to set up a packet filter on the host.

One solution might be to transparently route a VM through the TOR network so that a VM does not need to be modified in any way. It is quite simple and should work on all OS although I just tried it on a Linux host. As already said, the VM can run any OS!

The host must to redirect all TCP packets to a transparent SOCKS proxy which itself forwards the packets to a TOR client. UDP packets with destination port 53 are redirected to a small script which puts the payload into a TCP packet and forwards it to a TOR client. This is necessary because TOR itself can only handle TCP packets. The host must drop all other packets coming from the VM.

How this works under a Linux host:

  • Create an unprivileged user “torbob” that runs the VMs.
  • Choose a virtualization software. I decided to go for qemu/kvm since I am already familiar with it. Using Virtualbox or VMware should also work.
  • Install, configure and run a transparent SOCKS proxy. I use redsocks but there are also others around. Remember the port it is listening on (31337 in this case). Update: This is not necessary anymore, because Tor has an inbuilt SOCKS proxy since version 0.2.0.1-alpha. Just add “TransListenAddress 127.0.0.1″ and “TransPort 31337″ to your torrc.
  • Configure and run the tor-dns-proxy.py script from dsocks which does the UDP->TCP packet DNS conversion and remember the port it is listening on (1253 in this case). Update: This is not necessary anymore, because Tor has this inbuilt since version 0.2.0.1-alpha. Just add ” DNSListenAddress 127.0.0.1″ and “DNSPort 1253″ to your torrc. If you want to be able to resolve .onion domains, you also have to add “VirtualAddrNetwork 10.192.0.0/10″ to your torrc.
  • Redirect the packets from the VM to the local daemons:

iptables -A OUTPUT -t nat -p tcp -m owner –uid-owner torbob -j REDIRECT –to-ports 31337
iptables -A OUTPUT -t nat -p udp –dport 53 -m owner –uid-owner torbob -j REDIRECT –to-ports 1253

  • Make sure that packets to that daemons are accepted and all other packets from that user are dropped/logged:

iptables -A OUTPUT -d 127.0.0.1/32 -p tcp -m tcp –dport 31337 -m owner –uid-owner torbob -j ACCEPT
iptables -A OUTPUT -d 127.0.0.1/32 -p udp -m udp –dport 1253 -m owner –uid-owner torbob -j ACCEPT
iptables -A OUTPUT -m owner –uid-owner torbob -j LOG
iptables -A OUTPUT -m owner –uid-owner torbob -j DROP

  • If you want to share files through SMB between the host and the VM you have to add a few more rules *before* the rules above:

iptables -A OUTPUT -t nat -d 127.0.0.1/32 -p tcp -m tcp –dport 445 -m owner –uid-owner torbob -j RETURN
iptables -A OUTPUT -t nat -d 127.0.0.1/32 -p tcp -m tcp –dport 139 -m owner –uid-owner torbob -j RETURN
iptables -A OUTPUT -d 127.0.0.1/32 -p udp -m udp –dport 137 -m owner –uid-owner torbob -j ACCEPT
iptables -A OUTPUT -d 127.0.0.1/32 -p tcp -m tcp –dport 445 -m owner –uid-owner torbob -j ACCEPT
iptables -A OUTPUT -d 127.0.0.1/32 -p tcp -m tcp –dport 139 -m owner –uid-owner torbob -j ACCEPT

  • Thats it. Now starting a VM (or running any other program) as user “torbob” will either route its traffic through the TOR network (or drop the packets if they use an unsupported protocol).

This entry was posted by ra on February 03, 2010 at 6:43pm. It is filed under Linux, Security, Web. You can follow any comments to this entry through the RSS 2.0 feed.

Feel free to read the comments, or leave one of your own!

Also, if you're feeling social, you can Digg this, add it to del.icio.us, add it to Technorati, or add it to Newsvine!

comments are closed.