# OpenBSD, vmd, openvpn and packet filter

The need: I need to test some custome release of OpenBSD, FreeBSD and VoidLinux.

The answer: OpenBSD has its own hypervisor, vmd, already used by many people around the world, even for production ready services (e.g. openbsd.amsterdam). I need to deploy quickly lot of virtual machine on my laptop to test custom builds and some interconnected services (simulate internal network). Why OpenBSD? Because I removed FreeBSD on my laptop for more than 1 year now, and use only OpenBSD-current on it.

Okay, here a small schema:

  __________
 |          |
 | laptop   |
 |         [192.168.1.X/24]                          [public_ip]
 |  ______/ |    _____       ________      _________/     ________
 | |      | |   (     )     (        )    |         |    (        )
 | | iwm0 |----( local )---( internet )---| openvpn |---( internet )
 | |______| |   (_____)     (________)    | server  |    (________)
 |   /|\    |                             |_________|
 |  __|___  |
 | |      | |
 | | tun0 |---[10.X.Y.Z/24]
 | |______| |  
 |          |__
 |  _________  |
 | |         | |
 | | vether0 |---[172.16.1.1/24]
 | |_________| |
 |  ____|____  |
 | |         | |
 | | bridge0 | |
 | |_________| |________________
 |  ____|_     ____       ____  |
 | |      |   |    |     |    | |
 | | tap0 |---| vm | ... | vm | |
 | |______|   |____|     |____| |
 |_________\____________________|
            [172.16.1.X/24]

# Install OpenBSD

My installation is totally standard. You can how to install openbsd on https://www.openbsd.org.

# Configure OpenVPN

You can read my past article (https://medium.com/@niamtokik/vpn-solution-on-openbsd-hiding-openvpn-with-sslh-12d7cededfca) on this subject. Sorry about medium.com, I need to extract it and create something more... Free and usable.

# Enable services

We will enable all required services at first and start them later.

rcctl enable openvpn # if its not already the case
rcctl enable vmd
rcctl enable dhcpd

# Network Interface Configuration

# Packet Filter Configuration

First thing, I like to create a small organized tree:

mkdir -p /etc/pf.d/tables
mkdir -p /etc/pf.d/anchors
chmod -R 700 /etc/pf.d

I don't want to modify all default configuration on OpenBSD, so, I will just add an anchor in /etc/pf.conf.

echo "anchor vmd" >> /etc/pf.conf

Ensure your configuration is working and reload it

pfctl -nf /etc/pf.conf && pfctl -f /etc/pf.conf

We can now check if our anchor is ready to use:

pfctl -a vmd -sr

# Configure network interface

I like vether interface, I use them a lot! I think it is not necessary to use them everywhere, but, when you like something you know...

touch /etc/hostname.vether0
echo "inet 172.16.1.1/24" >> /etc/hostname.vether0
echo "up" >> /etc/hostname.vether0
sh /etc/netstart vether0
ifconfig vether0

Now our bridge interface.

touch /etc/hostname.bridge0
echo "add vether0" >> /etc/hostname.bridge0
echo "up" >> /etc/hostname.bridge0
sh /etc/netstart bridge0
ifconfig bridge0

We will use also some forwarding, we need to configure sysctl

sysctl net.inet.ip.forwarding=1
sysctl net.inet6.ip6.forwarding=1
echo "net.inet.ip.forwarding=1" >> /etc/sysctl.conf
echo "net.inet6.ip6.forwarding=1" >> /etc/sysctl.conf

# Configure dhcpd

Well this is pretty straighforward. I use a public DNS service, but you can use yours with unbound.

subnet 172.16.1.1 netmask 255.255.255.0 {
    range 172.16.1.32 172.16.1.64;
    option routers 172.16.1.1;
    options domain-name-servers 1.1.1.1;
}

We can now start dhcpd.

rcctl start dhcpd

# Configure vmd

I like to store everything I need for my vm at the same place:

mkdir -p /home/vmm/disk
mkdir -p /home/vmm/iso

I can now create my virtual disk:

vmctl create -s 10G /home/vmm/disk/openbsd65.qcow2

We need now to edit /etc/vm.conf

vm "openbsd65" {
    memory 1G
    disk "/home/vmm/disk/openbsd65.qcow2"
    interface { switch "uplink" }
    cdrom "/home/vmm/iso/openbsd65.iso"
}

switch "uplink" {
    interface bridge0
}

seems pretty nice! we can start vmd.

rcctl start vmd

and see if my vm is up and running.

vmctl show

and... attach to the console!

vmctl console openbsd65

# Now the trick

Okay, when I am working somewhere, I like to be connected to my VPN, but sometime, the connection is not usable, so, I switch to the classical way... But, with this configuration, I have some issue with the NAT configuration. I will add only a simple anchor in my packet filter to control it automatically.

When I start my OpenVPN and want to use it for my VM:

echo 'pass out from 172.16.1.0/24 to any nat-to (tun0)' | pfctl -a vmd -f -

When my tunnel is down:

echo 'pass out from 172.16.1.0/24 to any nat-to (iwm0)' | pfctl -a vmd -f -

Nice right? you can also add these function in OpenVPN configuration (see --up and --down flags).