Creating an IKEv1 IPSec VPN on OpenBSD

· 5min · Dan F.

Today I will be going over how to bring up a L2TP+IPSec VPN on OpenBSD. I am doing this because while I have been operating my own WireGuard VPN servers for the past few months now, I have experienced issues when the WireGuard server initiates over 100 connections. I know WireGuard is obviously still beta software, and that the issues could be caused by multiple things, but I wanted to give another option a shot.

Having set up WireGuard VPNs multiple times, I can say that setting up this new VPN was slightly more complicated, as there are more moving parts. However, the tools install on OpenBSD have been around a long time and have been thoroughly bug tested. Though, WireGuard does seem to be a quicker setup. However, the tools available in OpenBSD, namely ipsecctl, isakmpd, pppd and pf definitely have the ability to be tweaked more than WireGuard at this time.

1. Apply proper sysctl parameters to server

/etc/sysctl.conf

net.inet.ip.forwarding=1
net.inet.gre.allow=1
net.pipex.enable=1

Enable all settings by running this for loop:

for i in $(cat /etc/sysctl.conf); do sysctl $i;done

2. Setup npppd

Next up, we need to configure npppd. The default config already has the complete framework set, however, we do need to tweak the last few lines slightly. We want the tunnels to utilize a single interface for now, and the default is to create an interface per-session. Modify the ending of npppd.conf to be as below:

/etc/npppd/npppd.conf

# use pppx(4) interface.  use an interface per a ppp session.
#interface pppx0 address 10.0.0.1 ipcp IPCP
#bind tunnel from L2TP authenticated by LOCAL to pppx0

# use tun(4) interface.  multiple ppp sessions concentrate one interface.
interface tun0  address 10.0.0.1 ipcp IPCP
bind tunnel from L2TP authenticated by LOCAL to tun0

3. Create users

Now we need to create a user to log in as over the tunnel. Modify the existing npppd-users file with a user at the bottom of the file:

/etc/npppd/npppd-users

<username>:\
    :password=<password>

4. Create ipsec tunnel

Creating an ipsec tunnel on openbsd is rather simple. We simply need to add a couple lines into the ipsec.conf. You can specify one of multiple security "groups", of which the default is modp3072. As apparently this is rather high, we can also drop down the level of security, but do so at your own discretion. You can read about the groups with man ipsec.conf. iPhones will not authenticate above modp1024 to the best of my knowledge. The password listed here is the "group" password requested from clients when they connect.

/etc/ipsec.conf

ike passive esp tunnel from <server public ip> to any \
    main group "modp1024" quick group "modp1024" \
    psk "<password>"

5. Configure the firewall

This is the configuration that I am going with currently on my testing VPN server. This is pretty bare, and could obviously be tweaked for your own purposes.

/etc/pf.conf

vpn_if = "tun0"
vpn_net = "10.0.0.0/24"

set loginterface egress

set skip on { lo enc0 }

block return    # block stateless traffic

match out log on egress inet from !(egress:network) to any nat-to (egress:0)

# allow esp protocol
pass in log on egress proto esp

# allow ssh connection
pass in log on egress proto tcp to any port 22

# allow tcp and udp connections for ipsec and l2tp
pass in log on egress proto { tcp udp } to port { 500 4500 1701 }

# allow icmp requests
pass in log on egress proto icmp

# allow all IPSec traffic
pass log on enc0 keep state (if-bound)

# Allow IPv4 traffic in on vpn interface
pass in on $vpn_if inet

# allow all traffic out to the VPN network
pass log on $vpn_if to $vpn_net
pass out log on egress from any to any keep state

6. Bring up VPN

Now we will actually start the VPN server.

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

# Inject ipsec.conf
ipsecctl -f /etc/ipsec.conf

This should initialize the tunnel, allowing clients to connect to the VPN server.

You can check to see if clients have created ipsec flows with ipsecctl -sa. You can also see if any clients are logged in npppd with the command npppd session all.

More notes

For more info, read the docs from the folks over with OpenBSD.

Updated 06/09/2019

After further research and testing, it turns out that chromebooks require a very specific set of encryption settings in order for them to connect to an L2TP VPN. Such settings can be noted here.

In order to allow chromebooks to connect, the following ipsec.conf is required:

ike dynamic esp transport from <vpn ip> to any \
    main group "modp1024" auth hmac-sha1 enc 3des\
    quick group "modp1024" auth hmac-sha1 enc 3des \
    psk "<my psk>"

Has been tested on OpenBSD 6.5