Title: VMM Networking
Date: October 11, 2016
Tags: openbsd
========================================

Started playing with OpenBSD's virtual machine hypervisor again and got a NATed
networking configuration working.

I last played with VMM pretty much when it was first committed to the tree.
There was no networking at the time so usage was limited.  It's come a long way
so I decided to see how far I could get with it now.

Initially, I wanted what other hypervisors call *bridged* networking where the
VM acts like it's on the LAN and gets it's own IP the same way the host would.
Once I started digging into this, I realized that I have no idea how that
actually works.  If my host network adapter is talking to my LAN for the host
system, what makes it send and receive packets for the VM's IP/MAC?

If someone knows if that is possible on OpenBSD, let me know. *EDIT:*  Turns out
this is because I am using a wireless interface and they can't do such things.

So instead, I had to settle for a NAT setup with an internal "VM network" on the
host and access to the LAN via the host's IP.

# Fire up a VM #
Create a VM to play with.  Create a disk image and manually start it with vmctl.
I'm assuming you know how to enable vmm in your kernel and that you have /bsd
and /bsd.rd on your system.


 vmctl create disk1.img -s 5G
 vmctl start vm1 -c -k /bsd.rd -m 1024M -d disk1 -i 1


This should boot the ramdisk and connect you to the console to install OpenBSD.
Stop there while you set up the networking.  If you need to drop out of the
console, you can type '~.' to get back to the host.  You'll find a new tap
device will already exist on the host.

# Configure networking #
You need to bridge the VM's tap interface with a virtual interface on the host
so the host can talk on the "VM network".  Static IPs will be used in the VM so
we don't need a DHCP server on the VM network.

*EDIT:*  Instead of using a virtual interface as the gateway, you could give the
tap interface the 10.10.10.1 IP directly.  Problem there is that you'll have to
re-add the IP each time you boot the VM.


 ifconfig vether0 10.10.10.1 netmask 255.255.255.0
 ifconfig vether0 up
 ifconfig bridge0 create
 ifconfig bridge0 add vether0
 ifconfig bridge0 add tap0
 ifconfig bridge0 blocknonip vether0
 ifconfig bridge0 blocknonip tap0
 ifconfig bridge0 up


In the VM, you'll use a static IP on the 10.10.10.0/24 network, 10.10.10.1 as
the gateway and your LAN DNS server.

# Configure PF #
Enable packet forwarding and add a NAT rule to pf.  My LAN is on the
192.168.1.0/24 subnet so I chose 10.10.10.0/24 for my VM network.


 sysctl net.inet.ip.forwarding=1


 vm_net = "{ 10.10.10.0/24 }"
 match out on egress inet from $vm_net to any nat-to (egress:0)
 pass in quick on vether0 from $vm_net to any


I will probably turn this into an anchor so I can load and unload the rules as I
use a VM instead of having stagnant rules in my pf config.  Maybe make vm_net a
table and dynamically add IPs of specific VMs.


You can now install OpenBSD in the VM with full networking.  If you disconnected
from the console, get the VM id with `vmctl status` and connect with
`vmctl console <id>`.  Additional VMs can be brought up and their tap device
added to the bridge.


Some caveats:  Even if you leave the networking set up, once the VM shuts down,
the tap interface will be destroyed.  When the VM boots, you will have to re-add
it to the bridge  This will be fixed soon as the bridge information will become
part of the VM's configuration.  *Edit:*  This was implemented right after I
first posted.  See "Switch Configuration" in vm.conf(5).

Also, a `reboot` inside the VM seems to shut it down and you'll have to restart
it [and re-add the tap device to the bridge] <- ignore that bit.