This article provides a footnote on how to set up an OpenBSD-based VPN client that can connect to a VPN server running by Unifi Network Solution on Unifi USG.

Unifi Network Configuration

The first part of the article summarized the requirements for configuring the VPN server on the Unifi Network side. Unfortunately, available options are very limited and it forces some non-obvious and undocumented steps:

  1. VPN type is L2TP.1
  2. Pre-Shared Key and Radius Secret should match.
  3. Require Strong Authentication option should be disabled.1

Consequently, an alternative approach based on WireGuard, which is natively supported by OpenBSD, exists. This approach necessitates the installation of additional software from WireGuard for Ubiquiti project.

IPsec Tunnel

The second section of an article summarizes the required IPsec tunnel settings on the OpenBSD side.

Let us start with the definition of the IPsec connection in /etc/ipsec.conf:

ike dynamic esp transport proto udp from any to IP port l2tp \
	main auth "hmac-sha1" enc "aes-256" group modp4096 lifetime 3600 \
	quick auth "hmac-sha1" enc "aes-256" group modp4096 lifetime 3600 \
	psk "SECRET"

where IP is the VPN server used and SECRET is the pre-shared key.

Due to the limitations of Unifi Network Solution, we should enforce the used mode and cryptographic transformation parameters for phases 1 and 2.2

After that, the isakmpd daemon must be enabled, and we also use the ipsec pseudo daemon to load the configuration from /etc/ipsec.conf on boot:

rcctl enable ipsec
rcctl enable isakmpd
rcctl set isakmpd flags -K

The next step is to start isakmpd and load the configuration by hand:

rcctl start isakmpd
ipsecctl -f /etc/ipsec.conf

IPsec tunel takes some time to get up and running. It is possible to check the status by output ipsecctl -sa, which should look like this when tunel is up and running:

FLOWS:
flow esp in proto udp from A.B.C.D port l2tp to W.X.Y.Z peer A.B.C.D srcid my.client.fqdn dstid A.B.C.D/32 type use
flow esp out proto udp from W.X.Y.Z to A.B.C.D port l2tp peer A.B.C.D srcid my.client.fqdn dstid A.B.C.D/32 type require

SAD:
esp transport from A.B.C.D to W.X.Y.Z spi 0x0d16ad1c auth hmac-sha1 enc aes-256
esp transport from W.X.Y.Z to A.B.C.D spi 0xcd0549ba auth hmac-sha1 enc aes-256

L2TP Tunnel

The last section of an article summarized the required L2TP settings on the OpenBSD side to automatically route the required networks into the VPN.

OpenBSD doesn’t provide an L2TP client by default, so you will need to install xl2tpd: :3

pkg_add xl2tpd

The first step is to comment out or remove the forced auth option in /etc/ppp/options.

The next step is to add the _xl2tpd user to the network group to allow the use of ppp:

usermod -G network _xl2tpd

and allow group network to use doas to change the route table by adding the following to /etc/doas.conf

permit nopass :network cmd route

After that we should prepare the xl2tpd configuration in /etc/xl2tpd/xl2tpd.conf:

[global]
port = 1701

[lac NAME]
lns = IP
autodial = yes
redial = yes
redial timeout = 15
pppoptfile = /etc/ppp/options.NAME

where IP is the VPN server used and NAME is a resanable constant.

The next step is to prepare pppd options for this connection, which should be placed in /etc/ppp/options.NAME, where NAME should match the constant used in /etc/xl2tpd/xl2tpd.conf:

ipcp-accept-local
ipcp-accept-remote
noccp
noauth
mtu 1456
mru 1456
lock
ipparam NAME
user USERNAME
netmask 255.255.255.255

here you should replace NAME again and fill in the correct USERNAME.

The same USERNAME and used password should be used in /etc/ppp/chap-secrets in format:

USERNAME	*	PASSWORD	*

note that PASSWORD should be used without any any encryption.

The next step is to prepare /etc/ppp/ip-up to update the route table:

#!/bin/sh

export IPPARAM=$6

case "${IPPARAM}" in
    NAME)
        doas route -n add NET ${IPREMOTE}
        ;;
esac

where NAME is the same constant and NET should be changed to CIDR. of the network to be routed in the VPN. So this file should have executable permissions.

After that, we need to start ppp0 on boot by adding a line to /etc/hostname.ppp0 with a line up and run it:

sh /etc/netstart ppp0

And the final step is to enable and run the xl2tpd daemon:

rcctl enable xl2tpd
rcctl start xl2tpd

and we can check the status of the L2TP tunnel via ifconfig ppp0, which should look like this when the tunnel is running:

ppp0: flags=8051<UP,POINTOPOINT,RUNNING,MULTICAST> mtu 1456
	index 31 priority 0 llprio 3
	groups: ppp
	inet A.B.C.D --> W.X.Y.Z netmask 0xffffffff

  1. Unfortunately, Unifi Network Solution doesn’t provide a way to use IKEv2. This limitation forces to disable required MSCHAPv2 authentication due to lack of support by used pppd on OpenBSD side. As of February 2024. ↩︎ ↩︎

  2. Refer to the /etc/ipsec.d/tunnels/remote-access file on the Unifi USG in use for an acceptable list of cryptographic parameters. ↩︎

  3. Unfortunately, the xl2tpd port has issues in the documentation at /usr/local/share/doc/pkg-readmes/xl2tpd. Validated on OpenBSD 7.4. ↩︎