VirtualBox Host Interface Networking with NAT
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.
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. For brevity, I’ll just show eth0, but if you have multiple interfaces, feel free to use the same command for each of them.
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 eth0 -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

on September 23rd, 2008 at 8:19 am
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 ;)
on October 7th, 2008 at 8:21 am
it’s work perfect for me.
thanks a lot
on October 30th, 2008 at 2:04 pm
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.
on October 30th, 2008 at 3:05 pm
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!
on November 7th, 2008 at 10:10 am
Great! Thanks!
on November 10th, 2008 at 3:36 am
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
on November 10th, 2008 at 9:10 am
Drop me an email using the information found on my contact page. It sounds like either a basic routing decision issue.
on November 14th, 2008 at 4:54 am
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
on November 14th, 2008 at 8:22 am
@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.
on November 14th, 2008 at 10:22 am
Fantastic – thanks a bunch!!! I missed the “interface name” field. Once again, thank you!
on November 20th, 2008 at 7:39 pm
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
on November 21st, 2008 at 4:22 pm
Make sure that you don’t have any iptables rules blocking your forwarding.
on November 23rd, 2008 at 6:17 pm
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 !
on December 2nd, 2008 at 11:48 pm
You sir, rock my fucking world! After roughly 30 some odd links on this subject, finally one that makes clean sense.
on December 6th, 2008 at 12:41 pm
Awesome!! Works like a charm!!
on January 28th, 2009 at 6:06 pm
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!
on January 29th, 2009 at 11:17 am
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.
on February 7th, 2009 at 6:03 pm
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.
on February 8th, 2009 at 10:30 am
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.
on March 3rd, 2009 at 4:26 am
Hello webmaster
I would like to share with you a link to your site
write me here preonrelt@mail.ru
on April 3rd, 2009 at 10:17 pm
Great Tutorial, may repost in my Blog ? I want to share to my friend in Indonesia.
on April 4th, 2009 at 6:35 am
Sure thing! Glad to have helped.
on April 9th, 2009 at 7:46 am
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!
on April 21st, 2009 at 2:42 am
How will i use the this script? can you guys provide some steps? many thanks!
on April 21st, 2009 at 9:10 am
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.
4. Run the scripte from the command line.
on April 23rd, 2009 at 3:15 am
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!
on April 23rd, 2009 at 9:58 am
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.
on May 18th, 2009 at 11:49 am
[...] IPtables Tutorial IPTables Port Redirect VirtualBox, com nat VBoxManage Port Forward Linux porta, redirecionamento, [...]
on June 10th, 2009 at 1:28 pm
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!
on June 30th, 2009 at 12:14 pm
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 ?
on July 2nd, 2009 at 1:31 pm
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