OpenBSD 6.0 VPN Endpoint for iOS and OSX

Being able to remotely connect to my home network over VPN has always been on my ‘nice to have’ list. It allows easier access to resources and direct ssh (rather then hoping through the gateway). I have recently updated the OpenBSD server I used for VPN to 6.0 and thought I would share the configuration and settings.

I am a fan of using OpenBSD for anything security related, it is arguably the most secure UNIX-like operating system.

There are many VPN appliances commercially available that provide a nice UI and often come with an expensive support contract. If you are willing to roll up your sleeves a little and don’t mind using the command line, it is possible to create your own VPN server with OpenBSD.

The following instructions will cover configuring up an OpenBSD server behind a firewall that will provide a VPN endpoint.


The steps below will setup an IPSec VPN, with a ‘road warrior’ type configuration, where the external connections will likely have changing IP addresses. This is as opposed to a site to site VPN, where the external connection will be fixed.

As well I use primarily OSX and iOS devices, so the configuration details will focus on those devices, using the native drivers provided by the OS.

Finally, the server that will be in VPN endpoint will be behind a firewall and have the appropriate ports forwarded to it.

IPSec / L2TP

Device Support, native drivers:
OSX El Capitan (10.11), Sierra (10.12)
iOS 9, 10


Perform a normal OpenBSD 6.0 install, optionally install sudo and enable the wheel group in /etc/sudoers or perform the following as root.

The base install includes pf, ipsec and npppd so no additional packages should be needed.

Set the hostname of the OpenBSD VPN server by editing /etc/myname and set a host name.

Finally, assign a static ip address.

Network and Firewall Configuration

NOTE: How to configure the network, add static routes and port forwarding will depend on your DHCP / DNS / Firewall and is out of scope of this document. Often for small networks DHCP server, DNS server and Firewall are provided by the same gateway router.

For this configuration the network details are:

– OpenBSD Server:
– Private network: (
– DHCP / DNS / Firewall:
– VPN network pool:
– VPN network gateway to private network:

As the OpenBSD VPN server is not publicly facing the Internet, VPN traffic will need to be forwarded to the server. On your Firewall, you will need to make the following changes:

– Add static route from to access ip
– Forward UDP port 4500 to
– Forward UDP port 500 to


npppd is a Point-to-Point Protocol (PPP) and tunnelling daemon that will be used provide L2TP.

The default /etc/npppd/npppd.conf configuration file provides network details for L2TP for the can be left untouched.

Optionally, if you want to add a local DNS ( in this example) make the following changes:

The /etc/npppd/npppd-users configuration file stores the username, plaintext password and optional assigned ip address and is used for L2TP authentication. Add any users to this file:


The /etc/ipsec.conf file configures rules and definitions for IPsec.

IPsec is a pair of protocols, Encapsulating Security Payload (ESP) and Authentication Header (AH), which provide security services for IP datagrams.

Create /etc/ipsec.conf:

NOTE: Update XXX.XXX.XXX.XXX to your public facing IP address. This will need to be updated if your external Firewall ip changes.

NOTE: The SHARED_SEEKRIT is the shared secret that all users will use.

Set file permissions and reload:

NOTE: /dev/pppx0 will be created by l2tp when VPN is up.

NOTE: ifconfig will list pppx0 when the VPN is up.

Packet Filter

Packet Filter (PF) is OpenBSD’s system for filtering TCP/IP traffic and doing Network Address Translation. It is the native OpenBSD Firewall. For more details please see the OpenBSD PF User’s Guide.

The /etc/pf.conf configures PF and will have to be changed to allow forwarded VPN traffic in and out:


The sysctl utility sets and gets the kernel state, including ip forwarding and pipex (which handles PPP frames and forwards IP packets in-kernel).

The /etc/sysctl.conf file will apply the kernel state configuration after restart:


The /etc/rc.conf.local is used at start up to configure the system daemons, including IPSec and L2TP daemons.

The /etc/rc.conf.local will need to be configured to set isakmpd_flags, ipsec and npppd_flags :

Reboot the OpenBSD server.


That is it, simple right? 🙂

Well it is a little more complicated then a VPN appliance UI, but hopefully the steps aren’t too confusing.

Listed below are how to setup an OSX client and some management tips (starting and stoping, examining running VPN connections).

Any edits or suggestions are welcome.

OSX 10.12 Sierra Client VPN

Here are the steps to setup an OSX 10.12 Sierra Client VPN:

– Open System Preferences, select Network
– In the left pane, at the bottom, click on + to add an interface

– In dialog box:
Interface, select VPN
VPN Type, select L2TP over IPSec
– Set the Service Name
– Click Create

– In the left pane, select the newly created VPN entry, it should be Not Configured
– In the right pane:
Server Address, set to external IP address for the network (XXX.XXX.XXX.XXX)
Account Name, set to username from npppd-users (jappleseed)

– In the right pane, click on Authentication Settings....
User Authentication, Password, set to to password from npppd-users (USER_SEEKRIT)
Machine Authentication, Shared Secret set to psk from ipsec.conf (SHARED_SEEKRIT)


Monitoring different interfaces:

To monitor npppd vpn sessions use npppctl:

To monitor ipsec use ipsecctl:

View sysctl settings:

Display all routing tables:

Follow Up

It has been suggested that I should check out OpenIKED, which looks really promising. An OpenBSD project, appears to have native support on OSX and iOS (as well as broader client support on other OSes). If I have time, I look forward to trying it out.

3 Responses to “OpenBSD 6.0 VPN Endpoint for iOS and OSX”

  1. rjc Says:

    Hi Gordon,

    A couple of suggestions:

    1. No need to install ‘sudo’ – use doas(1) which is base.

    2. No need to hand edit ‘/etc/rc.conf.local’ any more – use rcctl(8).

    3. Piping to grep is unnecessary:

    sysctl net.inet.ip.forwarding
    sysctl net.pipex.enable

    Also, why reboot? :^)



  2. gturner Says:

    Thanks for the feedback!

    1. My muscle memory still gets me to type sudo (I blame Linux and OSX). I will eventually get used to doas, I think…

    2. Good to know about rcctl

    3. Edit made

    Eh, rebooting because old habits die hard? 🙂

  3. rjc Says:

    No worries.

    After years of using sudo, I very quickly retrained and eventually had to create doas -> sudo symlink on macOS and Linux machines I manage :^)