Creating a Virtual Network of Linux Guests using VirtualBox (Old Version)

As of September 2013, the instructions on this page have been replaced by a new set of instructions. I've kept this page just for reference. If you want to setup a virtual network I recommend reading my new instructions.

When teaching data communications and network security, I like to allow students to see and use real networks and software that demonstrate basic concepts. Although I teach a lab on networking where students get some hands on experience, I also like students to be able to try things in their own time. Creating a small network (e.g. a client, router and server) is not feasible for most students as they usually only have a single computer (most often a laptop, sometimes a PC at home). Hence the two options available is to ask students to use network simulation software or to setup a virtual network inside their own computer. This article gives instructions for the latter.

Virtual machine software, like VirtualBox, VMWare and Parallels, allow one or more guest operating systems to run as an application on another host operating system. The host OS runs on real hardware (your computer), while the guest OS run on virtual hardware, which is hardware emulated by the virtual machine software. The guest OS plus emulated hardware can be simply referred to as a virtual machine.

One part of hardware emulated by the virtual machine software is a network interface cards. Virtual machine software also emulates network devices, like switches, cables and routers. So a virtual network can be built by creating multiple virtual machines and connecting them together via virtual cables and switches.

I will use VirtualBox, free virtual machine software that runs on Windows, Linux and Macintosh host operating systems, and supports most operating systems as guest. As most of my teaching uses Ubuntu Linux in demonstrations, and students need to gain experience with the Linux command-line for other courses, I will use a command-line only install of Ubuntu Linux as each of the guests. Specifically, I will use Ubuntu 12.04.2 LTS Server. For most of the networking and security tasks I want to demonstrate, a simple network of three computers is sufficient: A - B - C. A and B are on one IP subnet, while B and C are on another (i.e. B is a router). The following instructions will explain how to setup the first virtual machine. The instructions can be repeated to setup the other virtual machines. In some cases we may need more hosts/routers to demonstrate other network/security technologies. Just repeat the instructions to create further nodes.

There are five steps to setup the virtual network containing three computers. Then to test the network and configure it to make some tasks easy, which is optional, there are an additional three steps.

  1. Setup Ubuntu as a guest using VirtualBox
  2. Install Ubuntu and update software
  3. Clone the base VM to 3 new VMs
  4. Setup networking on VMs in VirtualBox
  5. Setup networking on VMs inside Ubuntu
  6. Test networking [optional]
  7. Accessing virtual machines using SSH [optional]
  8. Starting virtual machines on the command-line [optional]

Step 1. Setup Ubuntu as Guest using VirtualBox

I am currently using Ubuntu Server 12.04 LTS 32-bit, so I recommend using the same version. Download the .iso from Ubuntu or from a local mirror. The file name will be something like ubuntu-12.04.2-server-i386.iso and about 700 MB in size.

In VirtualBox, create a new virtual machine, called Base. Two parameters that you must choose for your VM are:

When you start the VM for the first time, VirtualBox prompts for a disc (iso) to boot from. Select the downloaded Ubuntu .iso image.

An example of the steps I used for setting up the virtual machine in VirtualBox are presented as a set of screenshots here.

Step 2. Install Ubuntu and Update Software

The Ubuntu installation is rather straightforward. Most default options can be chosen, although there are a few important values. Rather than describe them here, I've provide a set of screenshots from my install that lists the important values. See the screenshots for my Ubuntu install before proceeding.

Once Ubuntu is installed and running, you should update the existing software packages and install some additional packages. Use the apt-get to update and install as follows:

$ sudo apt-get update
$ sudo apt-get upgrade
$ sudo apt-get install iperf wget lynx man-db manpages manpages-dev iputils-tracepath traceroute tcpdump nano ethtool telnet iptables iputils-arping ettercap-text-only dnsutils iptraf whois

Some optional packages that you may consider installing include: build-essential subversion.

Shutdown the VM using the poweroff command:

$ sudo poweroff

Step 3. Clone the Base VM to 3 New VMs

Naming Virtual Machines

When I first wrote these instructions I planned on using just three virtual machines, hence the names Client, Router and Server. The following instructions, as well as other pages, refer to these names. However I have since started using more virtual machines, and expect in some cases three will be sufficient, while in more complex scenarios five or six will be needed. Hence I now recommend using a different naming scheme. For example, node1, node2, ... . In the future I may update these instructions to use the new naming scheme. In the meantime, I recommend you replace the virtual machine names and host names from client, router, server, to node1, node2, and node3, respectively.

Now we are going to copy (clone) the base VM and create three new VMs: Client, Router and Server. Keep the Base virtual machine in case you want to create further clones in the future.

In VirtualBox, select the Base VM and choose to Clone it. Select the name to be Client and to "Reinitialize the MAC address". Use a "Full clone".

VirtualBox cloning of base VM: reinitialize the MAC address
VirtualBox cloning of base VM: reinitialize the MAC address
VirtualBox cloning of base VM: Full clone
VirtualBox cloning of base VM: full clone

Repeat the cloning for Router and Server.

Step 4. Setup Networking on VMs in VirtualBox

By default, VirtualBox creates a guest with one network adapter configured to use NAT. That allows the guest to have Internet access (but not act as a server nor contact other VMs). Visually, our three VMs currently look like this:

Topology for virtual network with NAT only
Topology for virtual network with NAT only

For our virtual network we want to create a simple network that connects client to router, and router to server. However to simplify the management of the VMs, they should each also have Internet access (e.g. so software updates can be performed) and allow remote SSH connections (e.g. so you can connect to the guest via the host using SSH). The network configuration we are aiming for is in the following figure.

Topology for virtual network with NAT and two internal networks
Topology for virtual network with NAT and two internal networks

The first step is to give the VMs extra network adapters. In VirtualBox, find the Network settings to see a list of 4 potential network adapters. Adapter 1 is already enabled on each VM and doesn't need changing. We need to add new adapters though.

VirtualBox settings for network adapter 1 on client
VirtualBox settings for network adapter 1 on client

For Client, enable Adapter 2 and attach it to Internet Network. Give the internal network a name like "neta".

For Router, enable Adapter 2, attach to Internal Network with name "neta" (the same as for Adapter 2 of Client). Then enable Adapter 3 with the same settings as Adapter 2 except with a different network name, e.g. "netb".

For Server, enable Adapter 2, attach to Internal Network with name "netb" (the same as for Adapter 3 of Router)

For virtual machines using the same internal network (e.g. Client and Router on "neta"), VirtualBox treats them as if they are connected to the same Ethernet switch.

For all adapters on each of the three VMs you should:

The following three screenshots how an example setup of each of the Routers adapters.

VirtualBox settings for network adapter 1 on router
VirtualBox settings for network adapter 1 on router
VirtualBox settings for network adapter 2 on router
VirtualBox settings for network adapter 2 on router
VirtualBox settings for network adapter 3 on router
VirtualBox settings for network adapter 3 on router

The last step is to allow remote access from the host to each guest using SSH. For each VM, select Adapter 1 and then click on the Port Forwarding button. A window opens that allows you to add a new rule. The rule should be:

VirtualBox settings for port forwarding on client
VirtualBox settings for port forwarding on client

The Host Port can be any unused port number, but it should be different for each VM. For example, set Client to 2201, Router to 2202 and Server to 2203. I will show how to use this later.

Step 5. Setup Networking on VMs inside Ubuntu

Start your Client virtual machine.

Unfortunately the way the VMs were cloned and MAC addresses reinitialized, Ubuntu guest still has a record of the MAC address from the original Base VM. It tries to use those (non-existent) MAC address upon boot, meaning a network connection will not be established. You most likely will see some warning messages as below when you boot:

Waiting for network configuration...
Waiting up to 60 more seconds for network configuration ...
Booting system without full network configuration...

To fix this problem, once booted, login and change to the /etc/udev/rules.d directory and edit the file 70-persistent-net.rules using nano:

$ cd /etc/udev/rules.d
$ sudo nano 70-persistent-net.rules

You will see some comments (starting with #) and lines starting with SUBSYSTEM. For these lines, look for the MAC address of your adapters in the ATTR{address} field. There will be a line that has a "wrong" MAC address - one that isn't for the Adapters. You must delete (or comment out by starting with a #) that line. Optionally, for the remaining lines with the matching MAC addresses, you may change their NAME. I recommend for Adapter 1, the name is "eth0", for Adapter 2 the name is "eth1".

Save the file in nano by pressing Ctrl-X, Y to save the modified buffer, and Enter to use the same file name.

Next you can change the hostname by editing /etc/hostname

$ cd /etc
$ sudo nano hostname

and change the name to "client".

Also change the hostname in the /etc/hosts file, which look like after you change base to node1:

27.0.0.1       localhost
127.0.1.1       node1

# The following lines are desirable for IPv6 capable hosts
::1     ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters

Now configure addresses for the interfaces. The first interface, eth0, should be configured to use DHCP. VirtualBox includes a DHCP server that allocates IP addresses to guests. The second (and for the router, third) interface should be configured with static IP addresses. This configuration is performed in the file /etc/network/interfaces. Edit the file with nano so it contains:

auto lo
iface lo inet loopback

auto eth0
iface eth0 inet dhcp

auto eth1
iface eth1 inet static
    address 192.168.1.10
    netmask 255.255.255.0
    network 192.168.1.0
    broadcast 192.168.1.255
    post-up route add -net 192.168.0.0 netmask 255.255.0.0 gw 192.168.1.1 dev eth1
    pre-down route del -net 192.168.0.0 netmask 255.255.0.0 gw 192.168.1.1 dev eth1

Finally reboot:

$ sudo reboot

You need to repeat the above steps for both Router and Server virtual machines. In summary, for each virtual machine you:

  1. Edit /etc/udev/rules.d/70-persistent-net.rules settings the correct MAC addreses.
  2. Set the hostname in /etc/hostname.
  3. Configure the IP addresses of interfaces by editing /etc/network/interfaces.
  4. Reboot the virtual machine.

The configuration of /etc/network/interfaces for Router is:

auto lo
iface lo inet loopback

auto eth0
iface eth0 inet dhcp

auto eth1
iface eth1 inet static
    address 192.168.1.1
    netmask 255.255.255.0
    network 192.168.1.0
    broadcast 192.168.1.255

auto eth2
iface eth2 inet static
    address 192.168.2.2
    netmask 255.255.255.0
    network 192.168.2.0
    broadcast 192.168.2.255

And for Server:

auto eth0
iface eth0 inet dhcp

auto eth1
iface eth1 inet static
    address 192.168.2.20
    netmask 255.255.255.0
    network 192.168.2.0
    broadcast 192.168.2.255
    post-up route add -net 192.168.0.0 netmask 255.255.0.0 gw 192.168.2.2 dev eth1
    pre-down route del -net 192.168.0.0 netmask 255.255.0.0 gw 192.168.2.2 dev eth1

Step 6. Test Networking [Optional]

[This step is optional. If the preceeding steps were completed correctly, then the networking should work. However note for Internet access you may need to add a route - skip to the end of this step to see how.]

Once all three virtual machines have been configured and rebooted, you should test that the network configuration is working as expected. Start all three machines and login to each.

Check the IP addresses of each interface. Here is an example for my Client machine:

network@client:~$ ifconfig
eth0      Link encap:Ethernet  HWaddr 08:00:27:08:ac:e6  
          inet addr:10.0.2.15  Bcast:10.0.2.255  Mask:255.255.255.0
          inet6 addr: fe80::a00:27ff:fe08:ace6/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:168 errors:0 dropped:0 overruns:0 frame:0
          TX packets:137 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:82361 (82.3 KB)  TX bytes:12969 (12.9 KB)

eth1      Link encap:Ethernet  HWaddr 08:00:27:65:8a:b7  
          inet addr:192.168.1.10  Bcast:192.168.1.255  Mask:255.255.255.0
          inet6 addr: fe80::a00:27ff:fe65:8ab7/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:191 errors:0 dropped:0 overruns:0 frame:0
          TX packets:314 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:27517 (27.5 KB)  TX bytes:29667 (29.6 KB)

lo        Link encap:Local Loopback  
          inet addr:127.0.0.1  Mask:255.0.0.0
          inet6 addr: ::1/128 Scope:Host
          UP LOOPBACK RUNNING  MTU:16436  Metric:1
          RX packets:13 errors:0 dropped:0 overruns:0 frame:0
          TX packets:13 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0 
          RX bytes:1156 (1.1 KB)  TX bytes:1156 (1.1 KB)

The 1st address, 10.0.2.15 was automatically assigned by the VirtualBox DHCP server. By default, VirtualBox assigned addresses to machines on the 10.0.2.0/24 network. The 2nd address, 192.168.2.20, is a static address chosen by you and set in /etc/network/interfaces. The 3rd address os the loopback address.

You should also check that the addresses for Router and Server are as expected.

Now lets test connectivity between the three virtual machines using ping. On Client:

network@client:~$ ping -c 3 192.168.1.1
PING 192.168.1.1 (192.168.1.1) 56(84) bytes of data.
64 bytes from 192.168.1.1: icmp_req=1 ttl=64 time=0.799 ms
64 bytes from 192.168.1.1: icmp_req=2 ttl=64 time=0.848 ms
64 bytes from 192.168.1.1: icmp_req=3 ttl=64 time=0.836 ms

--- 192.168.1.1 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2002ms
rtt min/avg/max/mdev = 0.799/0.827/0.848/0.039 ms
network@client:~$ ping -c 3 192.168.2.2
PING 192.168.2.2 (192.168.2.2) 56(84) bytes of data.
64 bytes from 192.168.2.2: icmp_req=1 ttl=64 time=0.791 ms
64 bytes from 192.168.2.2: icmp_req=2 ttl=64 time=0.837 ms
64 bytes from 192.168.2.2: icmp_req=3 ttl=64 time=0.834 ms

--- 192.168.2.2 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2001ms
rtt min/avg/max/mdev = 0.791/0.820/0.837/0.039 ms
network@client:~$ ping -c 3 192.168.2.20
PING 192.168.2.20 (192.168.2.20) 56(84) bytes of data.
64 bytes from 192.168.2.20: icmp_req=1 ttl=63 time=1.58 ms
64 bytes from 192.168.2.20: icmp_req=2 ttl=63 time=1.55 ms
64 bytes from 192.168.2.20: icmp_req=3 ttl=63 time=1.52 ms

--- 192.168.2.20 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2003ms
rtt min/avg/max/mdev = 1.529/1.556/1.584/0.050 ms

The first two tests show that Client has connectivity with Router, while the third test shows there is connectivity between Client and Server (which is via Router).

Lets now try Internet connectivity by using wget to download a webpage. The intention is to use eth0, which connects via the VirtualBox router to the real interface of the host.

network@client:~$ wget -t 1 http://sandilands.info/
--2013-06-21 13:28:55--  http://sandilands.info/
Resolving sandilands.info (sandilands.info)... 106.187.46.22
Connecting to sandilands.info (sandilands.info)|106.187.46.22|:80... failed: Connection timed out.
Giving up.

This didnt work! A connection could not be established to an external server. The reason is that there is no route to the VirtualBox router on IP 10.0.2.2. Lets check:

network@client:~$ route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         192.168.1.1     0.0.0.0         UG    100    0        0 eth1
10.0.2.0        0.0.0.0         255.255.255.0   U     0      0        0 eth0
192.168.1.0     0.0.0.0         255.255.255.0   U     0      0        0 eth1

So we need to add a route:

network@client:~$ sudo route add default gw 10.0.2.2 eth0
[sudo] password for network: 
network@client:~$ route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         10.0.2.2        0.0.0.0         UG    0      0        0 eth0
0.0.0.0         192.168.1.1     0.0.0.0         UG    100    0        0 eth1
10.0.2.0        0.0.0.0         255.255.255.0   U     0      0        0 eth0
192.168.1.0     0.0.0.0         255.255.255.0   U     0      0        0 eth1
network@client:~$ wget -t 1 http://sandilands.info/
--2013-06-21 13:34:58--  http://sandilands.info/
Resolving sandilands.info (sandilands.info)... 106.187.46.22
Connecting to sandilands.info (sandilands.info)|106.187.46.22|:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 1210 (1.2K) [text/html]
Saving to: `index.html'

100%[================================================================>] 1,210       --.-K/s   in 0s      

2013-06-21 13:34:58 (70.8 MB/s) - `index.html' saved [1210/1210]

Now we have Internet access on the Client machine.

In summary, if all the preceeding steps were completed correctly, networking between the virtual machines should be working. However to give each virtual machine Internet access you need to manually add a route to the VirtualBox router/gateway using:


$ sudo route add default gw 10.0.2.2 eth0

Step 7. Accessing Virtual Machines using SSH [Optional]

You can use the VirtualBox graphical interface to run and access the virtual guests. However often you may want to access the guests using applications on your host computer, e.g. web browser, file explorer, SSH client. I have moved this step to its own article that describes different ways to do so (for Linux, OSX and Windows hosts). This is optional - you don't need it to complete the setup of and use your virtual machines.

Step 8. Starting Virtual Machines on the Command-Line [Optional]

[This step is optional. It shows how to start the virtual machines on the command-line in a terminal. Its not needed, as you can simply use the VirtualBox GUI to start.]

VirtualBox provides an easy-to-use GUI to allow creating, configuring and running virtual machines. However it also provides a command-line interface to these operations, allowing you to avoid using the GUI. The command-line interface uses the program VBoxManage. Its available on Linux, Windows and Mac host operating systems. The advantage of using the command-line to start your virtual machines is that you can automate the procedure and may avoid clutter of multiple windows open on your desktop (especially when combined with SSH access described in Step 7).

Here I'll only show how to use VBoxManage to list and start virtual machines. Read the documentation for more operations. To view a list of available virtual machines, in a terminal (or Windows prompt) on your host machine type the following (note that VirtualBox does not need to be running):

sgordon@lime:~$ VBoxManage list vms
"Windows7" {f479c127-0f9e-458f-96c7-7cee310a6af4}
"Base" {f498f25b-4122-4695-b5fc-2111d08d6d4d}
"Client" {4266c522-94d6-4280-a9b9-a30edd829aae}
"Router" {c927c120-ffe9-416e-9ddd-3fb9d834b27a}
"Server" {0be369aa-29e6-4aba-b22e-875d349d5ee4}

You can start a virtual machine so that it opens in the VirtualBox GUI or runs without a GUI (called headless). If you are going to access the virtual machine using SSH as in Step 7, then you can use headless mode:

sgordon@lime:~$ VBoxManage startvm --type headless "Client"
Waiting for VM "Client" to power on...
VM "Client" has been successfully started.

Now use SSH to login to the virtual machine:

sgordon@lime:~$ ssh -p 2201 -l network localhost
network@localhost's password: 
Welcome to Ubuntu 12.04.1 LTS (GNU/Linux 3.2.0-23-virtual i686)

 * Documentation:  https://help.ubuntu.com/

  System information as of Fri Jun 21 15:43:38 ICT 2013

  System load:  0.0               Processes:           56
  Usage of /:   14.4% of 7.47GB   Users logged in:     0
  Memory usage: 11%               IP address for eth0: 10.0.2.15
  Swap usage:   0%                IP address for eth1: 192.168.1.10

  Graph this data and manage this system at https://landscape.canonical.com/

Last login: Fri Jun 21 14:23:35 2013 from 10.0.2.2
network@client:~$ 

You can poweroff the machine while logged in (recommended, e.g. using sudo poweroff) or you can use VBoxManage on the host:

sgordon@lime:~$ VBoxManage controlvm "Client" poweroff
0%...10%...20%...30%...40%...50%...60%...70%...80%...90%...100%

Next Steps

Now your virtual network should be up and running. You can start learning the command-line interface and then begin using some networked applications (e.g. wget, lynx, iperf, Apache, ssh, iptables, ethtool, ifconfig, route, ping).

I will provide some more guidelines and hints on setting up a virtual network (e.g. setting the link data rate and delay) soon.