Using host networking and NAT with VirtualBox, v2.0

Time marches on, and so do all those little changes in Linux distribution releases. Most of my really popular blog posts are how-to guides on complicated-but-useful procedures for the technical Linux user. Those users are the same ones who may read the date in the URL and say “Ewww, this was written three years ago, it must be totally outdated now!” I’ve decided to update the most popular posts to bring them up to date. This post is “Using host networking and NAT with VirtualBox“, version 2.0.

Version 1.0 of this guide had a good run. Very little changed between VirtualBox 2.0 and VirtualBox 4.0, or between Ubuntu 8.04 and Ubuntu 11.10. However, new screenshots are nice, and Ubuntu 12.04 onward requires a change in dnsmasq.

This updated guide assumes you are using VirtualBox 4.1.x from a Linux host running Ubuntu 12.04 “Precise Pangolin”. Similar commands can be used on any Debian or Ubuntu release since 2008. You’ll have to adapt some things to use it on RPM- or source-based Linux distributions. Assume all commands are run as root (directly or with sudo).

This guide enables IPv4 networking between VMs and the host OS. IPv6 networking is similar, but dnsmasq does not support DHCP on IPv6. If I write a guide to IPv6 auto-configuration and router advertisements, I will integrate it with these instructions.

Step 1: Create a bridge interface

First, we must create a bridge interface for the VMs. VirtualBox creates a “vboxnet0” interface by default, but this is not a bridge. Install the bridge utilities:

apt-get install bridge-utils

Now make the bridge start on boot. Add the following to /etc/network/interfaces:

# VirtualBox NAT bridge
auto vnet0
iface vnet0 inet static
        address 172.16.0.1
        netmask 255.255.255.0
        bridge_ports none
        bridge_maxwait 0
        bridge_fd 1
        up iptables -t nat -I POSTROUTING -s 172.16.0.0/24 -j MASQUERADE
        down iptables -t nat -D POSTROUTING -s 172.16.0.0/24 -j MASQUERADE

Either reboot or start it manually:
ifup vnet0

We now have a bridge interface to which VirtualBox can attach virtual machines. That traffic will be NATed to your host’s IP address when the guest OS accesses the Internet. However, the traffic won’t yet route.

Note: if you are already using a firewall such as iptables, shorewall, or ufw, you should remove the two iptables lines above and add equivalent commands to your firewall configuration. Otherwise NAT will probably not function.

Step 2: Enable IP forwarding

Now you must tell the kernel to route traffic. Find the ‘net.ipv4.ip_forward’ line in /etc/sysctl.conf, and uncomment it:

# Uncomment the next line to enable packet forwarding for IPv4
net.ipv4.ip_forward=1

And load it:
sysctl -p

Step 3: Setup DHCP and DNS for clients

OK, now you can forward and NAT traffic from client VMs. But you still have to configure static IPs in each guest’s OS. Here is where DNSMasq shines. It provides an all-in-one DHCP/DNS server in a small footprint. Install it:
apt-get install dnsmasq

And edit /etc/dnsmasq.conf to include:

interface=vnet0
domain-needed
dhcp-range=172.16.0.2,172.16.0.254,1h

As of Ubuntu 12.04, network manager runs a local dnsmasq resolver on localhost. This will conflict with our dnsmasq, which (despite an interface argument) also tries to run on localhost. Therefore we need to add:

bind-interfaces
except-interface=lo

It is safe to use these options on older releases or if you have disabled the network manager dnsmasq instance.

That’s all you need, but you may want to explicitly define DNS servers and domains for the guests, or set static assignments. Examples:

dhcp-option=option:dns-server,172.16.0.1,8.8.8.8,8.8.4.4
dhcp-option=option:domain-name,example.com
dhcp-host=08:00:27:00:00:02,windows,172.16.0.2
dhcp-host=08:00:27:00:00:03,lucid,172.16.0.3

This defines the host OS and the OpenDNS servers as the DNS servers (instead of passing on whatever your host OS uses), tells all guests they are part of the domain example.com, and defines two static assignments by MAC address.

My final dnsmasq.conf looks like this:

interface=vnet0
bind-interfaces
except-interface=lo
domain-needed
dhcp-range=172.16.0.2,172.16.0.254,1h
dhcp-option=option:dns-server,172.16.0.1,8.8.8.8,8.8.4.4
dhcp-option=option:domain-name,example.com
dhcp-host=08:00:27:00:00:02,windows,172.16.0.2
dhcp-host=08:00:27:00:00:03,lucid,172.16.0.3

Update 2013-02-01: On Ubuntu 12.10 or later, you must add the following undocumented variable to /etc/default/dnsmasq:

DNSMASQ_EXCEPT=lo

And restart dnsmasq:

service dnsmasq restart

Step 4: Set up the virtual machine

  1. Start VirtualBox Manager, highlight a VM, and select “Settings” from the toolbar or right-click menu.
  2. Choose “Network” on the left.
  3. Choose an adaptor, and check “Enable Network Adaptor”.
  4. For “Attached to:”, select “Bridged Adaptor”.
  5. For “Name:”, select the bridge you created in step 1, vnet0.
  6. If you assigned a static DHCP assignment above, expand the advanced settings and set the same MAC address.

Example:

Your virtual machines will now automatically receive an IP address in the 172.16.0.0/24 network, will resolve DNS, will NAT to your host’s external IP address, and can directly address each other.

Tags: , , ,

  1. dash’s avatar

    Thanks you.

    (subscribe)

    Reply

  2. Yves’s avatar

    Wow! Thanks a lot. This is valuable information.
    And congrats for using one of the unrecognized 172.16.0.0/12 private blocks :-)

    Reply

    1. Tyler Wagner’s avatar

      In my totally unscientific survey of RFC1918 IP usage (meaning “networks I’ve encountered”), the 172.16.0.0/12 space is almost never used. 192.168.0.0/16 is guaranteed to run into somebody’s home router, and 10.0.0.0/8 sees plenty of corporate uses.

      Reply

    2. Vance’s avatar

      If you’re using UFW, it’ll silently drop your packets for you instead of allowing the forward to take place.
      You’ll need to change:
      DEFAULT_FORWARD_POLICY=”ACCEPT”
      in /etc/default/ufw

      to apply:
      sudo ufw disable && sudo ufw enable

      then allow * to and from vnet0
      ufw allow in on vnet0
      ufw allow out on vnet0

      Reply

      1. Tyler Wagner’s avatar

        Thanks, Vance. I’m not using ufw. Is it mature enough yet to support NAT like the above? If so, please provide setup instructions and I’ll update the article.

        Reply

      2. Vndtta’s avatar

        Sorry for my unknowledge, I tried to follow your article and it doesn’t work, I’m guessing its the iptables step. Right now it shows that I have no rules, I tried to add the rule you mentioned but I don’t quite understand what I have to enter….

        Thanks

        Reply

      3. Rodrigo Nascimento’s avatar

        Many thanks for this, now I have best of both worlds!

        Note: Siince Im using static IP on the guest machines I did not need all the dnsmasq,conf tweaks, just the default configuration on Debian.

        Cheers

        Reply

Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.