-- Leo's gemini proxy

-- Connecting to gemini.splashgel.net:1965...

-- Connected

-- Sending request

-- Meta line: 20 text/gemini


↩ go back home


Setting up a public-facing IPv6 server with OpenBSD virtualization


Introduction

Suppose you want to run a service on a Linux VM via vmd, and want it accessible to the world. The process is slightly less straightforward than you might think, and less simple than if you're using IPv4. As an example, let’s say we're setting up nginx to run on Alpine Linux.


This goes page through the steps in detail to get things working, but to ‘skip-to-the end’ go to:


Very concise version


Setting up vmd

There are a number of different ways of setting up networking on a vmm guest. The easiest way is a local interface with NAT (option 2 in the FAQ).


OpenBSD FAQ - Virtualization


What the FAQ doesn’t mention is that by adding 'local inet6' at the top of 'vm.conf' you'll also get a unique-local routable subnet allocated. To be able to access the internet via the IPv4 side you need to add the NAT rules as specified in the FAQ to your pf.conf


match out on egress from 100.64.0.0/10 to any nat-to (egress)
pass in proto { udp tcp } from 100.64.0.0/10 to any port domain \
	rdr-to $dns_server port domain

Now create a disk with 'vmctl create -s 4G /mnt/data/alpine.img' or something similar. Then start the machine with 'vmctl start -c -L -m 1G -r alpine-virt.iso -d /mnt/data/alpine.img alpine' then install Alpine to the disk; to avoid creating a pointless swap partition cancel when it asks you about the disk setup then run 'setup-disk -s 0'. After installation you can create a vm.conf file as below so that the VM is saved.


vm.conf

local inet6

vm "alpine" {
	memory 1G
	disk /mnt/data/alpine.img
	local interface
}

Setting up Alpine


/etc/network/interfaces

auto eth0

iface eth0 inet dhcp
iface eth0 inet6 auto

Problems with this setup


If you look at the tap0 device on OpenBSD you will find it gives you an unpredictable address prefix, and so if you start running a server on it, you won’t know what address it will be on. This is explained on the OpenBSD mailing list.


vmd: add support for local inet6 interfaces


Setting up the VM networking again


The answer, therefore, is to go for option 3 in the FAQ, and set-up a bridge and a virtual switch. The FAQ shows how to set up an IPv4 subnet, but this needs to be tweaked by adding an IPv6 prefix. To generate your own local non-routable address block go here:


RFC4193 IPv6 Generator


Now your /etc/hostname.vether0 should look something like this:


inet 10.0.0.1 255.255.255.0
inet6 fdxx:xxxx:xxxx:xxxx::/64

Change the lines in pf.conf an vm.conf so that you have:


pf.conf

match out on egress from vether0:network to any nat-to (egress)

vm.conf

switch "my_switch" {
        interface bridge0
}

vm "alpine" {
        ...
        interface { switch "my_switch" }
}

remove the 'local interface' and 'local inet6' lines from vm.conf.


Setting up Alpine again


Change /etc/network/interfaces to


iface eth0 inet static
        address 10.0.0.100
        netmask 255.255.255.0
        gateway 10.0.0.1

iface eth0 inet6 static
        address fdxx:xxxx:xxxx:xxxx::xxxx/64
        scope site
        gateway fdxx:xxxx:xxxx:xxxx::1

Note that the addresses should match those in the vether0 setup in OpenBSD. 'scope site' is ignored in Alpine 3.17 but is correct. There is more information about setting up networking in Alpine at the wiki:


Alpine Linux Wiki: Configure Networking


The situation now


You have a VM with a predictable IPv6 address, but this can’t be reached by the global internet. Let’s pretend nginx is already set up on Alpine, there is a tutorial for doing this on the wiki:


Alpine Linux Wiki: https://wiki.alpinelinux.org/wiki/Nginx


Suppose the external address we want our server to be on is 2001:db8:100::99 then we have to add this to the external (i.e. egress) adapter’s addresses.


ifconfig fxp0 inet6 2001:db8:100::99

This can be made permanent by appending it to hostname.fxp0 (or whatever the adapter name is).


echo 'inet6 2001:db8:100::99' >>/etc/hostname.fxp0

You might think you can set pf up with 'rdr-to' so that packets can be redirected to this internal address, but you can’t. The answer now is to use relayd, which would be set up like this:


/etc/relayd.conf

relay "alpinevm_nginx" {
        listen on 2001:db8:100::99 port 80
        forward to fdxx:xxxx:xxxx:xxxx:xxxx port 80
}

-- Response ended

-- Page fetched on Sat May 18 23:40:56 2024