an9wer's

Virtual Machine Networking on OpenBSD

posted:

2025-09-27

Setting up network for a virtual machine on OpenBSD is extremely flexible. The easiest way is using the option -L while starting a virtual machine, which sets up network interfaces on both of the virtual machine and the host, without needing to manually assign network address. For example:

# vmctl start -m 512M -L -n 1 -b /bsd.rd vm0

It creates a virtual network (e.g. vio0) in the virtual machine, which can receive an IP address from vmd via DHCP. It creates a tap network interface (e.g. tap0) on the host, which simulates a layer 2 ethernet card and works as a bridge between the virtual machine and the host's network:

on vm0
# ifconfig vio0 autoconf
# ifconfig vio0
vio0: flags=808b43<UP,BROADCAST,RUNNING,PROMISC,ALLMULTI,SIMPLEX,MULTICAST,AUTOCONF4> mtu 1500
lladdr fe:e1:bb:d1:f1:00
llprio 3
groups: egress
media: Ethernet autoselect
status: active
inet 100.64.1.3 netmask 0xfffffffe

on host
# ifconfig tap0
tap0: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> mtu 1500
lladdr fe:e1:ba:d8:bc:ac
description: vm1-if0-vm0
index 37 priority 0 llprio 3
groups: tap
status: active
inet 100.64.1.2 netmask 0xfffffffe

This method works well for the virtual machine to communicate with (send packets to) the host and vice versa. However, for the situation when the virtual machine wants to access the network outside the host, it needs to set up NAT on host's egress network interface:

# ed /etc/pf.conf
a
match out on egress from 100.64.0.0/10 to any nat-to (egress)
.
wq
# pfctl -f /etc/pf.conf

An Alternative to the Option -L

Using the option -L is convenient as long as we don't mind that it offers addresses selected from the 100.64.0.0/10 IP range. Otherwise, we have to set up network manually with the desired IP ranges:

# vmctl start -m 512M -n 1 -b /bsd.rd vm0

This time, we start a virtual machine without using the option -L. However, just like when the option -L is used, it still creates a "vio" network interface in the virtual machine, and a "tap" network interface on the host. The only difference is that these network interfaces are created without any assigned IP addresses:

on host
# ifconfig tap0
tap0: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> mtu 1500
lladdr fe:e1:ba:d6:a3:11
description: vm1-if0-vm0
index 68 priority 0 llprio 3
groups: tap
status: active

on vm0
# ifconfig vio0
vio0: flags=8802<BROADCAST,SIMPLEX,MULTICAST> mtu 1500
lladdr fe:e1:bb:d1:b4:a1
llprio 3
media: Ethernet autoselect
status: active

Now, we can make our own decision to assign IP addresses to them - let's say from the IP range "172.16.0.0/24":

on host
# ifconfig tap0 172.16.0.1/24 up

on vm0
# ifconfig vio0 172.16.0.2/24 up

This approach achieves the same effect as using the option -L, but it gives us additional control over the IP address ranges.

Thanks for reading :)