Oracle VirtualBox: how do you reach a guest VM from the host OS?
Since what’s obvious to us old hands is sometimes less so for you, here’s my method to get two-way network access.
The approach
The goal is a Debian Linux VM with Internet access and access to its host OS. Conversely, we want the host OS to have access to the VM, so we can use it as a server. For example, a Docker container server.

Implementation
Let’s install a Debian Linux VM in Oracle VirtualBox, a type II hypervisor itself installed on my Windows 10 Home, itself installed on a basic hp laptop with a WiFi network interface and a LAN one (RJ45).By default, installing my Debian Buster Linux VM created a local interface 10.0.2.15, with gateway 10.0.2.2 (not a very happy choice: tradition is to pick the first“bit” (the first host address) i.e. 10.0.2.1).
Also by default, this VM can already connect to the Internet, through the NAT (Network Address Translation) virtual network interface, which lets the VM send its IP packets through a routable IP address and back. But . . . that’s not enough to receive connections from the host OS, because NAT is“outgoing only”! So in VirtualBox, for this VM, we’ll need to declare a second network interface in its own right, then configure it in Windows 10, in the network settings.
Choosing the network settings
Additional VM IP, known to the host OS
Let’s choose an IP for our second network interface, the one in its own right. Arbitrarily, but inspired by the boot2docker system, the other VM in my lab which uses guest IP 192.168.99.100, I choose IP 192.168.100.100.
Let’s also choose a gateway, 192.168.100.1, which will forward outgoing packets from the VM to Windows 10, and vice versa.
my VM’s hostname: sodium, alias sodium-docker.
Name this interface in a DNS system, the simplest being hosts.
Without wasting any more time, I declare these names in the Windows _DNS file_. A real DNS server would work too . . .
# Edit C:\WINDOWS\System32\drivers\etc\hosts (Windows 10), or /etc/hosts on Mac / Linux
# Add the below block
# Oracle VirtualBox
192.168.99.100 sodium-b2docker #boot2docker Linux Tiny Core
192.168.100.100 sodium sodium-docker
Declaring the interface + gateway
So I declare this {interface, gateway} pair in three places, as shown in the implementation diagram above:
1. In VirtualBox
Ctrl+S on the VM concerned, then the Network tab, Adapter sub-tabs. For this, the VM must be powered off. Go to the first free Adapter sub-tab, here no.2, and add an adapter of type VirtualBox Host-only Ethernet Adapter. This isn’t where we declare the IP. We’ll do that in the next step.

2. In the guest OS’s /etc/network/interfaces
Declare the network settings below there.
Reference:
wiki.debian.org/NetworkConfiguration
(as root, or use sudo)
root@sodium:~$ cp -p /etc/network/interfaces /etc/network/interfaces-
root@sodium:~$ vi /etc/network/interfaces
allow-hotplug enp0s8
iface enp0s8 inet static
address 192.168.100.100
network 192.168.100.0
netmask 255.255.255.0
gateway 192.168.100.1
broadcast 192.168.100.255
:wq
# activer cette interface
root@sodium:~$ ifup enp0s8
3. In the Windows 10 host OS
In the network settings. I renamed the interface created by the VM“Linux Debian Gwy”.

Note that there’s no need to declare a gateway for this interface, as Windows 10 will use the gateway of its WLAN or LAN connection to forward these packets to the rest of the network.
Connectivity test Host OS => Guest OS
C:\Users\Fabien Haddadi>ping 192.168.100.100
Pinging 192.168.100.100 with 32 bytes of data:
Reply from 192.168.100.100: bytes=32 time<1ms TTL=64
Reply from 192.168.100.100: bytes=32 time<1ms TTL=64
Reply from 192.168.100.100: bytes=32 time<1ms TTL=64
Reply from 192.168.100.100: bytes=32 time<1ms TTL=64
In pictures . . . 
Connectivity test Guest OS => Host OS
fhaddadi@sodium:~$ ping 192.168.100.1
PING 192.168.100.1 (192.168.100.1) 56(84) bytes of data.
64 bytes from 192.168.100.1: icmp_seq=1 ttl=128 time=0.729 ms
64 bytes from 192.168.100.1: icmp_seq=2 ttl=128 time=0.513 ms
64 bytes from 192.168.100.1: icmp_seq=3 ttl=128 time=0.542 ms
64 bytes from 192.168.100.1: icmp_seq=4 ttl=128 time=0.560 ms
A Windows bridging mechanism does the rest. It’s provided automatically by Windows. Its effect is that any IP packet bound for sodium or sodium-docker goes through the gateway
Internet connectivity test
fhaddadi@sodium:~$ ping mail.yahoo.com
PING edge.gycpi.b.yahoodns.net (77.238.180.12) 56(84) bytes of data.
64 bytes from e2.ycpi.vip.fra.yahoo.com (77.238.180.12): icmp_seq=1 ttl=49 time=25.5 ms
64 bytes from e2.ycpi.vip.fra.yahoo.com (77.238.180.12): icmp_seq=2 ttl=49 time=25.9 ms
64 bytes from e2.ycpi.vip.fra.yahoo.com (77.238.180.12): icmp_seq=3 ttl=49 time=26.4 ms
Using the VM
With two-way connectivity between the VM and the host OS, we can now:
- use the apt-get utility or any other package manager on the VM.
- connect to this VM with PuTTY over SSH, to avoid using the somewhat limited native VirtualBox console.
- Serve containers!
A quick example of running a container on the Debian VM
As a PoC (Proof of Concept), let’s start an Apache web server in a container managed by Docker.
How to
Logged into the VM as an unprivileged user, but a member of the sudo group (use usermod -aG sudo <user> to add a user to a group), install Docker if not done already.
Example: for Debian Linux, follow the official documentation here: docs.docker.com/engine/install
Then start the httpd container, listening on port 8080 of the IP in question, using the command line below:
sudo docker run -itd --ip=192.168.100.100 -p 8080:80 httpd
You should now be able to connect to this web server from the host OS. See the image below.

I hope this tutorial helped you. It certainly helped me.


