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).