Confine virtual machines

I am not an expert and I came out with a working hack for my need of isolating some VM in my virtual farm from the rest of other VMs.

I use Xen+libvirt. The ingredients for this receipt are:

  • a working vm
  • a persistent named tun interface that connects somewhere via VPN
  • policy routing

Let us call the existing VM goofy. It has a virtual NIC attached to a virtual bridge created with libvirt. This virtual bridge is in NAT mode.

<network connections='1'>
  <name>unsafe-nat</name>
  <uuid>fa91e8bf-6666-5555-4444-222211110000</uuid>
  <forward dev='tun-ovpn' mode='nat'>
    <nat>
      <port start='1024' end='65535'/>
    </nat>
    <interface dev='tun-ovpn'/>
  </forward>
  <bridge name='virbr3' stp='on' delay='0'/>
  <mac address='52:54:00:9a:ca:ca'/>
  <domain name='unsafe-nat'/>
  <ip address='192.168.126.1' netmask='255.255.255.0'>
    <dhcp>
      <range start='192.168.126.128' end='192.168.126.254'/>
    </dhcp>
  </ip>
</network>

As you can see, it is a bridge that includes all the virtual NICs of the VMs and an interface on my host, tun-ovpn, that I previously created with openvpn.

Now you can finish all this mess creating a new routing table, that I choose to be number 666

root@host $ ip route add to default via <vpn_gateway> dev tun_ovpn table 666
root@host $ ip route add to 192.168.126.0/24 dev virbr3 table 666

and creating a new rule to match the traffic from the subnet of the unsafe VMs

root@host $ ip rule add from 192.168.126.0/24 lookup 666

To end all of this, if you want to give access to this VM from the outside, but you don’t want to set up complicated NATing and routing rules, you can create a Tor hidden service inside goofy and bind it to ssh (adding these lines in /etc/tor/torrc)

HiddenServiceDir /var/lib/tor/ssh/
HiddenServicePort 22 127.0.0.1:22

The remaining is to secure your host from the VMs in 192.168.126.0/24 from being malicious.