Routing VM Traffic Through Tor
...first off, you can take all the fun out of this and simply use a distribution like TAILS which is probably exactly what you want anyway (it provides a VM with the "usual" tools you might want already configured to route through Tor, and to clean up information leaks afterwards).
The Fun Way
Instead, we will route all traffic coming out of our VM guest through a tor transparent proxy running on the host via iptables. You may read the ending first by looking at the script in this Gist on GitHub.
This is all on Debian Squeeze, which has packages for everything I'm using (apt-get install vde2 kvm tor iptables python). Presumably Ubuntu would work too.
For our VDE switch, we want a tap device also, through which we will receive the data on the host side. There, iptables rules will send it on its way via Tor (configured as a transparent proxy).
vde_switch -s /tmp/vde_switch_tor -tap tortap
Next, we wish to bring up the tap device with an IP address (on the host).
ifconfig tortap 10.0.0.210 up
Our VM is then launched and connected to the switch. On the VM, /etc/networks/interfaces may need to be changed to include information to bring up your interface (we don't have DHCP running, so we define something statically). Pick something different for the MAC address.
kvm -net nic,macaddr=00:00:00:00:00:00 -net vde,sock=/tmp/vde_switch_tor -m 128 -smp 1 -drive file=/path/to/image.qcow2
iface eth2 inet static address 10.0.0.5 netmask 255.255.255.0 gateway 10.0.0.210
Host Configuration
So far, we've only got a tap device and a VDE switch running on the host. We also need a Tor configured to be a transparent proxy [wikipedia]. Other options for a setup similar to this are available on the Tor wiki.
What we're going to do is take all the traffic arriving on the tap device and shovel it into Tor. Since Tor won't route any UDP besides DNS requests, we only forward port 53. We need at least a torrc configuration like so:
# possibly not needed for this example but this allows # .onion and .exit routes to "just work" AutomapHostsOnResolve 1 # this is where we'll send TCP traffic for proxying TransPort 9040 TransListenAddress 10.0.0.210 # just DNS requests will be sent here DNSPort 9053 DNSListenAddress 10.0.0.210 ## flesh out a few more options for a full config Log notice stderr RunAsDaemon 0 DataDirectory /home/mike/src/virtual-machines/tor
Presuming those ports don't conflict with the system-wide tor, you may start another one based on that config:
/usr/sbin/tor -f torrc
Then, we configure the host to take all data arriving on the tap device and give it to Tor. Note that I'm deleting all the nat rules with the first command; make sure that's what you want.
iptables -t nat -F iptables -t nat -A PREROUTING -i tortap -p udp --dport 53 -j REDIRECT --to-ports 9053 iptables -t nat -A PREROUTING -i tortap -p tcp --syn -j REDIRECT --to-ports 9040
There is similar, possibly more-detailed advice I've found for OpenWRT. As in: turning your linksys router into a transparent Tor proxy.
Now, we should be able to do some web surfing in the VM and it will all go through Tor. Of course, a handy way to check is to visit check.torproject.org.
Ship It!
It also seems prudent to run some tests ensuring that there is no traffic leaking from the VM. An easy one to check for (and a bad one to leak) are DNS requests. If you have OpenWRT or similar installed on your router along with tcpdump, that is likely the best bet; then you may capture all DNS requests entering the router from your network:
ssh root@your_router /usr/sbin/tcpdump -i any -s 0 -w - "port 53" > dns-leaks.pcap
Beware, of course, that this will capture from any host on your network so before you freak out if this file has anything in it, check which hosts the requests are coming from -- there shouldn't be anything from 10.0.0.3 or 10.0.0.210 if you've followed the IPs in this text. Next, simply do some surfing or at least host lookups in a "normal" fashion on the VM; you should see NO DNS traffic related to these requests hitting the router (they should be getting proxied via the Tor network and looked up at the exit node of whatever circuit gets used). Try some very weird hosts, like "short random text string".com.
Is It Useful?
Maybe.
This allows one to confidently use any program at all in the "torrified" VM without leaking any network traffic. It doesn't magically fix programs which don't use encryption properly and won't work with things which rely on UDP traffic (a general problem with Tor). If you use a read-only disk image for your VM, you can also be assured of a "known state" every time you start it up without relying heavily on TorButton to "do the right thing" with your browsing history, cookies, future clicks, etcetera.
Some of the Tor tutorials describe how to do the inverse of this, namely having a VM which "does" Tor stuff for you (and through which you'd route all host traffic). I personally don't see the usefulness of this; it makes it hard to switch between Tor'd and not-Tor'd things whereas with a "sandboxed" VM, it's easy to do "Tor" things in one area (the VM). Probably I'm missing something.