VirtualBox Host Interface Networking with NAT

Posted by admin on September 21, 2008 under Tech Tips | 40 Comments to Read

WARNING! THIS POST HAS BEEN MARKED AS OUTDATED!

While there may be useful information still contained within the article, there may be other more relevant articles out on the Internet. Please pay close attention to version numbers of software that this article refers to. If you're not careful, you could break your system if you do not understand what you are doing. If you would like to see this article updated, please contact the site administrator using the Contact page. Thanks!

UPDATE (12/13/2009): The latest versions of VirtualBox 3 have made great improvements in their guest networking options. It is now possible to natively bridge and NAT multiple guests behind a single virtual interface. The suggestions on this post still work fairly well, so I will leave it up as there is a great deal of useful information that come in handy in some scenarios. Please refer to the latest VirtualBox documentation for more help on using their native networking options.

ORIGINAL: Here’s a detailed tutorial on VirtualBox host interface networking with NAT for multiple guests.  I typically run a number of guests simultaneously for labs and product testing, so they all need internet access through my host, as well as full communication directly with each other.

The built in NAT interface of VirtualBox isn’t very flexible for what we want to do, so here’s a summary what what we will do. We’ll create three TAP interfaces, one for each guest, since TAP interfaces cannot be shared by multiple guests. These interfaces will serve as each guest’s default gateway, but all of the guests will use the same address space and subnet mask. For full communication between the guests, we’ll add appropriate host routes and enable proxy ARP on the host. Nothing will need to be configured on the guests accept for their IP address, subnet mask, default gateway, and DNS if needed.

Here’s a diagram of the virtual topology, which hopefully will make things a little more clear.

virtualbox host with NAT

VirtualBox Host Interface NAT Topology

Getting Started

You’ll need to install the User Mode Linux utilities first, if you have done so already.

sudo apt-get install uml-utilities

TAP interfaces

Let’s create three TAP interfaces.

sudo tunctl -u $USER
sudo tunctl -u $USER
sudo tunctl -u $USER

Assign IP addresses to the TAP interfaces.

sudo ip addr add 192.168.20.1/32 dev tap0
sudo ip addr add 192.168.20.2/32 dev tap1
sudo ip addr add 192.168.20.3/32 dev tap2
sudo ip link set tap0 up
sudo ip link set tap1 up
sudo ip link set tap2 up

Routing Requirements

Enable routing and add host routes for each of the guest IP addresses.

sudo sysctl net.ipv4.ip_forward=1
sudo route add -host 192.168.20.201 dev tap0
sudo route add -host 192.168.20.202 dev tap1
sudo route add -host 192.168.20.203 dev tap2

Proxy ARP

Enable proxy ARP on all TAP interfaces so that all the guests can communicate with each other.

sudo sysctl net.ipv4.conf.tap0.proxy_arp=1
sudo sysctl net.ipv4.conf.tap1.proxy_arp=1
sudo sysctl net.ipv4.conf.tap2.proxy_arp=1

Notice, it is NOT necessary to enable proxy ARP on the public interface, since we will be using NAT for guests to access the public network and internet.

NAT Configuration

First flush all iptables rules and enable NAT on the public interface.

sudo iptables --flush
sudo iptables -t nat --flush
sudo iptables -t nat -A POSTROUTING --out-interface eth0 -j MASQUERADE
sudo iptables -A FORWARD --in-interface tap0 -j ACCEPT
sudo iptables -A FORWARD --in-interface tap1 -j ACCEPT
sudo iptables -A FORWARD --in-interface tap2 -j ACCEPT

Now it’s just a matter of configuring each of your guests to use the appropriate host interface as shown in the screenshot below.

After assigning the guest to an interface, configure the guest operating system with the appropriate IP address and routing information. The following list will show the IP address configuration each guest should use for this example.

Guest 1
Host interface: tap0
IP Address: 192.168.20.201
Subnet Mask: 255.255.255.0
Gateway: 192.168.20.1
DNS: Any reachable DNS server.

Guest 2
Host interface: tap1
IP Address: 192.168.20.202
Subnet Mask: 255.255.255.0
Gateway: 192.168.20.2
DNS: Any reachable DNS server.

Guest 3
Host interface: tap2
IP Address: 192.168.20.203

Subnet Mask: 255.255.255.0
Gateway: 192.168.20.3
DNS: Any reachable DNS server.

And that’s it. Your guests should all be able to ping each other, and access the internet!

To make things easy, I have also created the following Bash shell script that creates and tears down the environment with ease. Modify settings to your liking.

#!/bin/bash
# tap-setup.sh
# By Gilbert Mendoza
 
# Change username accordingly
USER="gmendoza"
PROXY="tap0 tap1 tap2"
TAPS="tap0 tap1 tap2"
NAT_OUT="eth0 wlan0"
 
ip_setup(){
ip addr add 192.168.20.1/32 dev tap0
ip addr add 192.168.20.2/32 dev tap1
ip addr add 192.168.20.3/32 dev tap2
route add -host 192.168.20.201 dev tap0
route add -host 192.168.20.202 dev tap1
route add -host 192.168.20.203 dev tap2
}
 
nat_setup(){
iptables --flush
iptables -t nat --flush
for i in $NAT_OUT
 do
   iptables -t nat -A POSTROUTING --out-interface $i -j MASQUERADE
done
for i in $TAPS
 do
   iptables -A FORWARD --in-interface $i -j ACCEPT
done
}
 
tap_up(){
tunctl -u $USER
tunctl -u $USER
tunctl -u $USER
sysctl net.ipv4.ip_forward=1
for i in $PROXY
 do 
   sysctl net.ipv4.conf.$i.proxy_arp=1
done
for i in $TAPS
 do
   ip link set $i up
done
}
 
tap_down(){
sysctl net.ipv4.ip_forward=0
iptables --flush
iptables -t nat --flush
for i in $PROXY
 do
   sysctl net.ipv4.conf.$i.proxy_arp=0
done
for i in $TAPS
 do
   tunctl -d $i
done
}
 
if [[ $EUID -ne 0 ]]; then
  echo "This script must be run as root" 1>&2
  exit 1
else
 
case "$1" in
 
start)
	tap_up
	ip_setup
	nat_setup
	;;
stop)
	tap_down
	;;
*)
	echo "Usage: $0 {start|stop}"
	;;
esac
 
fi
 
exit 0

Using it is as simple as the following.

sudo tap-setup.sh start
sudo tap-setup.sh stop
Be Sociable, Share!

Comments

  • lorim said,

    great howto… i was doing this with parprouted on a wlan but sometimes pinging between guests doesn’t work, while with your howto it works 100% :) (maybe something isn’t working right in parprouted) thanks a lot! PS: you can also put the functions in some scripts that virtualbox can call when powering on the guests, so you can keep every settings “per-guests” and avoid having a lot of tap interfaces when you just need one ;)

  • palik said,

    it’s work perfect for me.
    thanks a lot

  • eDRoaCH said,

    Great tutorial, I appreciate it. However I remember you having 2, a ‘sandbox’ version and this one. It is nice you consolodated them but in the process you dropped the windows info. I cant remember how to enable the proxy arp on the network bridge.

    some of us dual boot you know.

  • eDRoaCH said,

    found it, Windows XP users:
    To create bridge:
    rclick My Network Places-> properties.
    select all adapters you want in the bridge
    rclick->bridge connections

    Enable promiscuous mode:
    start->run->cmd
    ( ‘>’ means type whats after it)
    >netsh bridge show a
    >netsh bridge set adapter # forcecompatmode=enable
    where # = whichever ones do NOT have ‘enabled on them’ in the list, one at a time.
    >netsh bridge show a
    to verify.
    Note you will loose network access for a minute or so after you create the bridge and each “set adapter” command

    enjoy!

  • Juan C. A. said,

    Great! Thanks!

  • tkgafs said,

    Thanks for this it works well, but for one small issue I have created a guest with two nics assigned to tap4 & tap5

    in the guest they are both seen as up and running and both can be pinged succesfully from the guest itself, but from any other guest or the host only 1 nic can be contacted, normally this is the guest eth0 but if run ifconfig eth0 down then the 2nd nic on eth1 starts replying to pings and stays online even if ifconfig eth0 up is run but eth0 remains unavailable.

    anybody got any suggestions as to what the problem might be

    Tkgafs

  • gmendoza said,

    Drop me an email using the information found on my contact page. It sounds like either a basic routing decision issue.

  • Ralf S. said,

    Thanks, exactly what I’m trying to implement. One question left: How do I bind tap0 (tap1, …) to a guest system? I just set IP data as mentioned and ran the tap-setup script, but the VMs do not see each other and Internet is not available to the guests neither.
    TIA, Ralf

  • gmendoza said,

    @Ralf

    Edit the network settings of your guest in VirtualBox and change the “Attached To” value to “Host Interface”. I added an additonal screenshot to the post to make it a bit more complete.

  • Ralf S. said,

    Fantastic – thanks a bunch!!! I missed the “interface name” field. Once again, thank you!

  • dicipulus said,

    hmmm, I can ping the real world. I can ping tap0′s gateway from tap1 and vice versa, but I can’t seem to get past the gateway of either to the hosts. Need to study routes and such better I think. I just am not seeing the issue

  • gmendoza said,

    Make sure that you don’t have any iptables rules blocking your forwarding.

  • okubax said,

    You are my hero. after months spent trying out different solutions and breaking my Linux (ubuntu) computer more than once, I have found a solution that works and so easy. Thanks for the script too, that makes it even easier.
    NOTE to some users with ufw enabled in ubuntu, ufw didn’t allow the connection to work until I disabled it then the interface started working.
    Thanks again !

  • Snaggletooth said,

    You sir, rock my fucking world! After roughly 30 some odd links on this subject, finally one that makes clean sense.

  • Vazemeazer said,

    Awesome!! Works like a charm!!

  • Ronald Baljeu said,

    Thanks! Great article. Very well documented.

    I would just like to add that Virtualbox 2.1.2 has a problem which prevents guests to see each other, when using your setup. Version 2.1.0 however works perfectly. I sent a bug report for this (#3215).

    Thanks again!

  • Ronald Baljeu said,

    Follow up: with version 2.1.0 or later, you can share a single host interface among multiple guests. This makes the setup much easier. Just create tap0 with IP 192.168.20.1/24, skip the host routes and proxy-arp, and setup all guests to use 192.168.20.1 as gateway. This works for 2.1.2, too. Hope this helps.

  • Alsan Wong said,

    Thanks very much for the sharing.
    One things, I can ping the guest through tapN from host, but I can’t access the service inside (ie: HTTP). This can be simply by testing “telnet 192.168.20.1 80″.
    So, how can I achieve this? Thanks in advance.

  • gmendoza said,

    Well, if all the instructions have been followed, typically connectivity issues arise with iptables firewall rules. I would flush any you have on the host and the client. Re-check connectivity, and use tcpdump on client and host to see where the problem is.

  • Alexwebmaster said,

    Hello webmaster
    I would like to share with you a link to your site
    write me here [email protected]

  • CyberThug said,

    Great Tutorial, may repost in my Blog ? I want to share to my friend in Indonesia.

  • gmendoza said,

    Sure thing! Glad to have helped.

  • z0n said,

    After many late nights trying to get my wifi interface bridged for vbox, I run your script and everything just works – without a single dodgy if-up script or weird, mystical manual interface setting.

    Excellent script, Dude – you must wear a beard, I’m sure ;>

    Many thanks – you rule!

  • gab said,

    How will i use the this script? can you guys provide some steps? many thanks!

  • gmendoza said,

    gab… my apologies for not explaining how to set up the script. my reasoning is that if I explain how to set it up, it becomes redundant across all of my posts.

    1. Save the script as a text file in a place you have “write” access to. Your home directory should be fine. Save it as “tap-setup.sh” or any other name you find appropriate.

    2. Copy the script to a directory referenced in your $PATH variable. I like to put my own custom scripts in “/usr/local/bin/”. This allows you to just type in the name of the script at the command line without having to type it’s absolute path.

    3. Make the script executable.

    sudo chmod +x /usr/local/bin/tap-setup.sh

    4. Run the scripte from the command line.

    sudo tap-setup.sh start
    sudo tap-setup.sh stop

  • gab said,

    Does it affect my current internet connection if I enable this script? I’m directly connected to a cable modem..

    Thanks for writing the steps. I appreciate your help!

  • gmendoza said,

    You run this script only when you need to start and use Virtualbox. After finished with Virtualbox and it’s all shut down, you can use it again with the stop option. It should not affect your internet connection at all, but if you have firewall rules turned on your host computer, you may need more fine tuning of your rules.

    You should know that if you just want to have your guests behind a NAT, this process has been made easier in the most recent versions of Virtualbox.

  • Redirecionando portas para VirtualBox. @ Matheus Bratfisch said,

    [...] IPtables Tutorial IPTables Port Redirect VirtualBox, com nat VBoxManage Port Forward Linux porta, redirecionamento, [...]

  • Mark Nicholas said,

    works great with Air Cards as well (ppp0) modify script from
    NAT_OUT=”eth0 wlan0″
    to
    NAT_OUT=”eth0 wlan0 ppp0″
    and voila! life is good

    thank you for the help!

  • scott said,

    I have been using something similar I believe @ work, but the problem is it is updating the DNS with my NAT IP address. Do one of the iptables rules above stop that from happening ?

  • edward said,

    With version 2.1.4 OSE of virtualbox you can just go to Settings -> Network: and change the “Attached to:” from “Nat” to “Host Interface”. Then select your host machine’s active network device from the list. Start up your guest and it should pick up an IP from your networks’ Dhcp server. If you have no DHCP server configure the guest with a static IP. Note, you may have to open a terminal and run dhclient3 as root or with sudo to get your guest to pick up an IP via dhcp. Otherwise it should just work. It did for me.

    thanks
    emk

  • Jorge said,

    Great post!

    But with this configuration, udp broadcast don’t work between client machines.
    Can anyone have a hint to solve this problem?

    Thanks in advance.

    Jorge

  • Marcello de Sales said,

    The search is over!!! VirtualBox 3.0.2 offers the networking with NAT out-of-the-box with Ubuntu as Host and Guests as Ubuntu and windows. See instructions! No commands, no scripts necessary!

    http://distributed-agility.blogspot.com/2009/07/building-clustered-shared-subnetwork.html

  • dent said,

    Nice write-up and just what the doctor ordered. For some reason vbox3′s builtin port forwarding on natted interfaces is very flaky when running in headless mode. This is much nicer!

  • Денис Лебедев said,

    Занятно пишете, жизненно. Все-таки, для того, чтобы делать действительно интересный блог, нужно не только сообщать о чем-то, но и делать это в интересной форме:)

  • boulboul said,

    i have setup sp many onterfaces,,,how do i go about deleting all taps please…i am running debian lenny…thanks

  • gmendoza said,

    The tunctl command creates interfaces temporarily and are not remembered after a reboot. To see if any exist, the following will work:

    ifconfig -a | grep tap
    tap0 Link encap:Ethernet HWaddr 52:da:12:03:e5:d5
    tap1 Link encap:Ethernet HWaddr 9a:7e:d5:2c:84:64
    tap2 Link encap:Ethernet HWaddr fa:ef:38:a0:b0:06
    tap3 Link encap:Ethernet HWaddr 62:fd:aa:0b:e0:46

    As you can see, I have four tapX interfaces. To remove them, use the tunctl -d command like the following.

    sudo tunctl -d tap0
    Set 'tap0' nonpersistent
    sudo tunctl -d tap1
    Set 'tap1' nonpersistent
    sudo tunctl -d tap2
    Set 'tap2' nonpersistent
    sudo tunctl -d tap3
    Set 'tap3' nonpersistent

    Hope this helps. Thanks for visiting.

  • boulboul said,

    Thanks a lot for your email…that has worked. You are great :)

  • Frank said,

    This is outdated and should be removed. Configuring the host to use tap0 in VirtualBox settings doesn’t work – the tap0 interface doesn’t exist in the Linux guest.

  • Frans said,

    Very good article !! Thank you for this, it really solves my problem.. ;)

Add A Comment