Iptables – How to route traffic from a VirtualBox VM only over a VPN

iptablesnetworkingvirtualboxvirtualizationvpn

I've got a VirtualBox VM (both host & guest Ubuntu Maverick). My VPN provider uses OpenVPN to setup TUNs. I'd like to set things up so that traffic from the VM only goes over the VPN and is just dropped if the VPN goes down (it's happened). Suggestions? My iptables-fu is a little weak

What I've tried: using VirtualBox's "host-only networking" which gives you a vboxnet0 loopback interface on the host to the guest, but couldn't get the iptables/routes right. I'd like to avoid NAT on VM, as I'm already double NAT'd (ISP & home router) and one more level will make my head pop.

Other possibilities: switching to TAP (how?) and bridging to VM. Creating VPN inside VM and filtering all eth0 traffic except VPN connect with iptables (but see below)

Bonus points: if you can tell me how to use different VPN exit points on host & guest without double-tunneling traffic from guest through the host's VPN.

Best Answer

There will be other solutions, but this is what I'm thinking:

  1. Setup the VM in bridge mode. This will give your virtual machine an IP address in the same network as your host.
  2. Setup the VPN on the host, let's say it's tun0.
  3. Enable routing on the host echo 1 > /proc/sys/net/ipv4/ip_forward
  4. Setup the VM with the host IP address as the default gw.

At this point, the host has the VPN connection, and the VM will route all traffic to the host. All that is left to do is restrict the host so that it does not allow the guest to route any traffic that isn't going to go thru the tun0 device. You could do that with a set of iptables rules something like this:

iptables -P FORWARD DROP
iptables -A FORWARD -o tun0 -j ACCEPT
iptables -A FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT

That should work. The first rule sets a default policy to DROP packets in the FORWARD chain. This only effects packets that your host would route, not packets to the host (INPUT) or from the host (OUTPUT). The second rule allows any traffic that is routing out tun0 - you could tighten that up with a --source if you wanted. And the last rule should let replies coming back from tun0 to route back to the VM.

Will your VPN be expecting all packets on the tun interface to be from a single IP? If so, you'll want to add a NAT rule as well. Probably something like:

iptables -t nat -A POSTROUTING -o tun0 -j SNAT --to-source {your host tun0 ip}