VirtualBox networking gives us several options. NAT is interesting because it protects our guest systems from the Internet but it’s annoying we need to setup port forwarding to access the guests from the host (I have servers on some guests). Bridged Networking solves that problem easily, but the guests are exposed (not acceptable) and it seems that the communication between guest and hosts is routed outside the machine: in my case the bytes go to the switch my ISP installed in my home and that’s does only 10 Mb/s. I can probably setup some manual routing to solve that problem but if I have to tinker with routing then I can get something better: the combination of both NAT and Bridged Networking.
My setup is:
- Host system: Ubuntu 10.10 with VirtualBox 4.0.4 (update: I’m on 11.04 and 4.1.8 now and it still works)
- Guest systems: two headless Debian 4 and Debian 6 servers, three Windows XP clients to run tests with IE6, IE7 and IE8 (all the other browsers run directly on Ubuntu with the exception of Safari.)
The desired network configuration is:
- The host eth0 interface must be the only access to the Internet
- A virtual interface inside the host system should NAT the guest systems
- The guest systems should be able to access the Internet using the internal NAT
- The guest systems should be able to communicate with the host system using the virtual interface
- The guest systems should be able to communicate with each other using the virtual interface
Internet <--- eth0 ---> HOST <--- virt/if (NAT) ---+---> guest 1 (server)
(server & client) |
+---> guest 2 (server)
+---> guest 3 (client)
With this configuration I can attach application servers to the address of the virtual interface and make them available to all the guest systems for testing, as well as to any application I run on the host system. I also want to access application servers on the guests so I’m going to use static addresses because I don’t want to setup a dynamic DNS for the internal network.
VirtualBox gives us a virtual interface called vboxnet0 which starts with the 220.127.116.11 IP address. I take advantage of that.
The problems to solve are
- Start vboxnet0 at boot time, because that address must be always available even if no guest OS is running.
- Setup the NAT.
- Assign addresses to the guest systems.
The procedure is based on https://help.ubuntu.com/community/Internet/ConnectionSharing but there are some differences.
The most important one is that connection sharing must not be enabled with the procedure shown there because it will change the address of your eth0 after a reboot and you won’t be able to access the Internet.
Configure the host
First, we bring up the virtual interface
sudo ifconfig vboxnet0 192.168.56.1
Then we configure NAT.
sudo iptables -A FORWARD -o eth0 -i vboxnet0 -s 192.168.56.0/24 -m conntrack --ctstate NEW -j ACCEPT
sudo iptables -A FORWARD -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
sudo iptables -A POSTROUTING -t nat -j MASQUERADE
Update: You lose the configurations on the vboxnet0 device if you remove VirtualBox to update it to a newer release. You have two options: 1) reboot and get them back from the configuration file (I’ll make you generate in the next steps of the procedure) or 2) just repeat the two steps above. I tested option 2 with the upgrade from 4.0 to 4.1.
We want to make those changes permanent.
sudo iptables-save | sudo tee /etc/iptables.sav
sudo vi /etc/rc.local
We add these lines
iptables-restore < /etc/iptables.sav
ifconfig vboxnet0 192.168.56.1
and we enable IP forwarding
sudo sh -c "echo 1 > /proc/sys/net/ipv4/ip_forward"
sudo vi /etc/sysctl.conf
with these lines
# Internet connection sharing for VirtualBox VMs
Update: VirtualBox still works with that configuration after updating to Ubuntu 11.04 so you can safely chose to keep that file when the update process asks you whether to keep it or overwrite it with the standard one. By the way, it seems that IP forwarding is done with net.ipv4.ip_forward=1 in 11.04 but I didn’t tried it out.
We can restart the networking or reboot (it’s fast).
netstat -r should give something like this now:
Kernel IP routing table
Destination Gateway Genmask Flags MSS Window irtt Iface
your.host.ip.addr * 255.255.255.192 U 0 0 0 eth0
192.168.56.0 * 255.255.255.0 U 0 0 0 vboxnet0
link-local * 255.255.0.0 U 0 0 0 eth0
default your.gw.ip.addr 0.0.0.0 UG 0 0 0 eth0
Configure the guests
Start VirtualBox. Change the network of every guest OS to be Host Only Adapter, vboxnet0
Startup every VM in turn and change it’s network configuration.
The configuration on the two Debian servers is a little complicated because they’re headless and everything must be done by command line.
sudo vi /etc/dhcp/dhclient.conf
prepend domain-name-servers comma_separated_list_of_DNS_ip_addresses;
Restart networking. That will update /etc/resolv.conf
sudo vi /etc/network/interfaces
Add a static address for eth0.
iface eth0 inet static
address 192.168.56.x # x is any free address in the 192.161.56 network
up route add -net 192.168.56.0 netmask 255.255.255.0 gw 192.168.56.1
down route del -net 192.168.56.0 netmask 255.255.255.0 gw 192.168.56.1
Restart the networking or reboot.
You should be able to ping 192.168.56.1 and access the Internet. Check it with
telnet http://www.google.com 80
From the host system you should be able to ping and ssh this server.
The configuration on the three Windows clients is easier, about as easy as on Ubuntu
Click Start, Control Panel, Network Connections.
Right click on the connection, Properties.
Select Internet Protocol (TCP/IP), click Properties.
Select Use the following IP address and enter
IP address: 192.168.56.x (x = an address you didn’t use yet)
Subnet mask: 255.255.255.0
Default gateway: 192.168.56.1
Preferred DNS server and Alternate DNS server: the addresses of the DNS of your provider.
Click OK and again OK.
You should be able to ping 192.168.56.1 and access the Internet. Start up a browser and check it.
From the host system you should be able to ping this machine.
I can start my application servers on the host system and bind them to 192.168.56.1 even if VirtualBox is not started (remember to update the addresses in their configurations, probably from 127.0.0.1 to 192.168.56.1).
I can access the Internet from my guest systems, which is handy for downloading updates, but the Internet cannot access them thank to the internal NAT. Too bad VirtualBox doesn’t give us this setup out of the box. The closest option is Bridged Network but the guest systems are exposed on the Internet.