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.
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 InterfacesEdit 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 DNSmasqDNSmasq 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 ForwardingUn-comment the following line in /etc/sysctl.conf:
Configure iptablesCreate 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)
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.