20150523

Giving VirtualBox Guests Access to the Internet Without Exposing the Host's Network

I have a virtual machine running under VirtualBox that needs to be able to get updates from the Internet. Using VirtualBox's normal network interface methods (NAT or Bridging), the guest machines not only have access to the Internet, but also to all the interfaces on the host machine and their networks! Googling around for a solution didn't turn up anything useful, and VirtualBox seems reluctant to provide a Internet only option either.
 
After trying for about a day to mess with various iptables solutions and coming up empty handed, I decided to try a different approach to the problem. My solution is to create another “router” virtual machine and connect the main virtual machine through it to the rest of the network. All network traffic for the guest would go through an “Internal Network” connection to the router VM, and then the router would provide NAT, DHCP, and DNS services for the guests. This solution also has the benefit of providing multiple guest VMs with Internet-Only connections.
 

The router VM is very lightweight and doesn't require too much in the way of resources. I used Ubuntu Server 14.04.2 (32 bit), creating a virtual machine with 512MB of RAM and 10GB hard drive. (You could probably get away with less RAM and drive space, but I haven't played with trimming it down yet.) The secret sauce is in how the network adapters for these machine are configured. For the guest machine, you need to set up a single network adapter on an “Internal Network” (named vbx-router in this case). You can do this from VirtualBox GUI or the command line as follows:
vboxmanage modifyvm "guest-vm-name" --nic1 intnet --intnet1 vbx-router

The router VM will have two adapters, the first one bridged to the host's main network interface (typically eth0 on Linux hosts), and the second one using the same internal network we defined for the guest VM. The command line for this would look something like:
vboxmanage modifyvm "router-vm-name" --nic1 bridged --bridgeadapter1 eth0
vboxmanage modifyvm "router-vm-name" --nic2 intnet --intnet2 vbx-router

After installing the Ubuntu 14.04.2 x32 Server (you can use your favorite flavor of non-GUI Linux, your mileage may vary), make sure it is up-to-date (sudo apt-get update and sudo apt-get upgrade on Ubuntu/Debian). It's also probably a good idea to install OpenSSH Server, especially if your virtual machines are headless like mine. Next, it's time to install and configure the routing services. These instructions are based off a really useful blog post over at The Novian Blog.
 

Configure the Interfaces

Edit the /etc/network/interfaces file so it looks similar to this:

# The loopback network interface auto lo iface lo inet loopback # The WAN (bridged) interface auto eth0 iface eth0 inet dhcp # The LAN (internal) interface auto eth1 iface eth1 inet static address 10.0.2.1 netmask 255.255.255.0 network 10.0.2.0 broadcast 10.0.2.255

You can set up the WAN interface with a static IP if you'd like, but the LAN interface should be static so that guest VMs can always find it. The addresses for the LAN interface were chosen to be similar to the default NAT configuration provided by VirtualBox.
 

Install and configure DNSmasq

DNSmasq is a simple to setup DHCP server and DNS forwarder, install it with the command:
sudo apt-get install dnsmasq

Then add the following to the bottom of /etc/dnsmasq.conf:
interface=eth1
domain=home.teknynja.com
dhcp-range=10.0.2.10,10.0.2.99,12h

Of course you will want to change the domain to something suitable for your network.
 

Enable IP Forwarding

Un-comment the following line in /etc/sysctl.conf:
net.ipv4.ip_forward=1

Configure iptables

Create the file /etc/iptables.rules:
*nat
-A POSTROUTING -o eth0 -j MASQUERADE
COMMIT

*filter
-A INPUT -i lo -j ACCEPT
-A INPUT -i eth0 -m state --state RELATED,ESTABLISHED -j ACCEPT
-A INPUT -i eth0 -p tcp -m tcp --dport 22 -j ACCEPT
-A INPUT -i eth0 -j DROP
COMMIT

*raw
-A PREROUTING -i eth1 -d 192.168.0.0/16 -j DROP
COMMIT

This configuration does the following:
  • Sets up NAT outbound on eth0
  • Allows all inbound localhost traffic
  • Allows inbound established connections
  • Allows SSH connections from WAN to our router
  • Drops anything else coming in from eth0
  • Drop packets coming from eth1 destined for host's local network(s)
Activate the rules (as a quick sanity check before rebooting!):
sudo iptables-restore < /etc/iptables.rules

Now try to ssh into the router and verify that you can connect. Once you verify that the rules are working, configure iptable rules to load on network startup. Add the following to /etc/network/interfaces after the line iface lo inet loopback:
pre-up iptables-restore < /etc/iptables.rules


 

Profit!

Reboot your router virtual machine to make sure it loads all your new configuration. Next double check your VirtualBox network configuration on the guest VM then go ahead start it. Check to make sure the guest picks up an IP address from the router VM, and proceed to test your guest's network. You should now be able to access the Internet, but be unable to access anything on your local network (including the host!)
 
Hopefully this will help you create an isolated guest with Internet access in your setup. I've been needing something like this for a while, and now that I've figured it out I felt like I needed to share. If you see anything wrong with this setup, or know how to make it more secure, please feel free to leave a comment.

0 comments:

 
Template design by Amanda @ Blogger Buster