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.

This is part of a series on setting up an OpenBSD VPN Endpoint.
The most current version is here:
OpenBSD 6.2 VPN Endpoint for iOS and macOS

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:

sudo vi /etc/npppd/npppd.conf
ipcp IPCP {
        # CHANGED

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:

sudo vi /etc/npppd/npppd-users
# $OpenBSD: npppd-users,v 1.1 2012/09/20 12:51:43 yasuoka Exp $
# sample npppd-users file.  see npppd-users(5)

#       :password=taro's password:\
#       :framed-ip-address=
#       :password=hana's password:\
#       :framed-ip-address=


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`:

sudo vi /etc/ipsec.conf
public_ip = "XXX.XXX.XXX.XXX"

ike passive esp transport \
  proto udp from $public_ip to any port 1701 \
  main auth "hmac-sha1" enc "aes" group modp1024 \
  quick auth "hmac-sha1" enc "aes" group modp1024 \

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:

sudo chmod 600 /etc/ipsec.conf
sudo ipsecctl -f /etc/ipsec.conf

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:

sudo vi /etc/pf.conf
#       $OpenBSD: pf.conf,v 1.54 2014/08/23 05:49:42 deraadt Exp $
# See pf.conf(5) and /etc/examples/pf.conf

set skip on lo

block return    # block stateless traffic
pass            # establish keep-state

# By default, do not permit remote connections to X11
block return in on ! lo0 proto tcp to port 6000:6010

# From `/etc/protocols`
# esp     50      IPSEC-ESP ESP   # Encap Security Payload
# ah      51      IPSEC-AH AH     # Authentication Header
pass quick proto { esp, ah } from any to self

# UDP 500  - Internet Key Exchange (IKE)
# UDP 4500 - IPSec Network Address Translation (NAT-T)
pass quick proto udp from any to self port {isakmp, ipsec-nat-t} keep state
pass on enc0 from any to self keep state (if-bound)


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:

sudo vi /etc/sysctl.conf


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` :

sudo vi /etc/rc.conf.local

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:

sudo tcpdump -ni enc0
sudo tcpdump -ni pppx0
sudo tcpdump -ni pflog0

To monitor npppd vpn sessions use npppctl:

npppctl session all

To monitor ipsec use ipsecctl:

sudo ipsecctl -s all

View sysctl settings:

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

Display all routing tables:

netstat -nr

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 :^)