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 :)