I recently had reason to examine some potentially malicious code at work and the safest way to perform this was to run the software within a VM. The problem was, how do you correctly configure a VM to limit how much network access it has, and thanks to LonnieOlsen’s blog on the topic it didn’t turn out to be too difficult. My requirements were fairly simple:
- The guest Windows XP machine must be able to resolve DNS names
- The guest Windows XP machine must NOT be able to access the local network (except for accessing the local DNS server)
- The guest Windows XP machine must be able to access the Internet using HTTP or HTTPS
- The guest Windows XP machine must be able to SSH to the host Ubuntu machine (to copy files if required)
As mentioned by Lonnie, the best way to do this is to configure the VM to use “Host Only” networking, then utilise the masquerading and other firewalling options of iptables on the Host Ubuntu system. This allows the Ubuntu system to limit, at the network layer, what the VM can access. My setup has the Ubuntu machine connecting to the network via wireless networking, the guest configured for “Host Only”, which uses the virtual interface vmnet1, and visually looks like this:
First up is configuring iptables. I’ve created a file called firewall and placed it in my /etc/init.d/ folder. The file has the following in it:
The script is a bash script, not much to explain here.
echo 1 > /proc/sys/net/ipv4/ip_forward
Enable IP forwarding in the linux kernel – otherwise the IP traffic wouldn’t be routed through the Host Ubuntu system.
iptables -t nat -F POSTROUTING
iptables -F FORWARD
Flush the tables before we set them up.
iptables -t nat -A POSTROUTING -s 172.16.72.0/24 -o wlan0 -j MASQUERADE
Enable routing out the wireless interface where the traffic comes from the “Host Only” virtual nat interface’s subnet.
Next we start the firewalling:
iptables -A FORWARD -i vmnet1 -p UDP –dport 53 -j ACCEPT
1. Allow DNS from the virtual nat interface. (requirement #1)
iptables -A FORWARD -i vmnet1 -d 192.168.0.0/24 -j DROP
2. Disallow traffic to enter the wireless network. (requirement #2)
iptables -A FORWARD -i vmnet1 -p TCP –dport 80 -j ACCEPT
3. Allow HTTP traffic out. (requirement #3)
iptables -A FORWARD -i vmnet1 -p TCP –dport 443 -j ACCEPT
4. Allow HTTPS traffic out. (requirement #3)
itpables -A FORWARD -i vmnet1 -j DROP
5. Drop everything else.
And that’s it (download the file from here). Don’t forget to add a symlink to this file in your boot up scripts, because the Linux iptables rules do not return to their previous state after you reboot:
$ sudo ln -sf /etc/init.d/firewall /etc/rc2.d/S89firewall
This puts the bash script into your default runlevel (2) and runs it after all the interfaces should be up.
Due to the way in which the forwarding works, the above rules will not prevent the Windows XP VM from SSHing to the Host Ubuntu box (requirement #4). But before we start up the VM, we have to configure the DHCP daemon settings for that “Host Only” virtual nat interface, vmnet1. The file we want to modify is /etc/vmware/vmnet1/dhcpd/dhcpd.conf, which I believe by default is read only, so the first thing I had to do was make it writeable with a:
$ sudo chmod o+w /etc/vmware/vmnet1/dhcpd/dhcpd.conf
The only changes I made to this file were the addition or modification of the following lines in the subnet 172.16.72.0 netmask 255.255.255.0 block:
option domain-name-servers 192.168.0.254
option routers 172.16.72.1
This explicitly sets the DNS settings to the ADSL Router/DNS Server – as my Host Ubuntu server does not provide DNS resolution, and the second option sets up the gateway setting so the Windows XP VM will route traffic towards the Host Ubuntu server.
Next we adjust the Windows XP VM so it’s using “Host Only” networking and boot it up and voila. Your Windows XP VM should boot up and acquire its network settings from the vmnet1 DHCP daemon settings, it should be able to resolve internet hostnames and should be able to access Internet sites over HTTP and HTTPS but that’s it. If it tries to connect to any of the PCs on your wireless network it shouldn’t be able to.
(In the nature of always wanting to find better ways to do things, if anyone has any suggestions for how this could be done better, because I’m sure it could be, please leave me a comment!)