OpenBSD 6.2 VPN Endpoint for iOS and macOS

The following instructions describe how to remotely connect to a network over an IPsec / L2TP VPN through an OpenBSD server, using native clients on macOS and iOS.

The most current version of OpenBSD is 7.1
I have not tested these steps on OpenBSD 7.1, but I would expect them to work without too much modification.


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.

These instructions assume familiarity with installing OpenBSD. Installing OpenBSD is not technically difficult, but familiarity with the command line and Unix/Linux commands is recommended. If you can install Linux, OpenBSD should not be a problem.

This is an update to the previous post OpenBSD 6.0 VPN Endpoint for iOS and OSX.

Alternative: OpenIKED

An alternative to the following instructions is the OpenIKED project. It is an OpenBSD project, appears to have native support from macOS and iOS.


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.

The client configuration will focus on macOS and iOS devices using native OS drivers. Other platforms include IPsec / L2TP support, please check your documentation and Google for details.

Finally, the instructions assume that the OpenBSD server is behind a firewall and have the appropriate ports forwarded to it. The server can be physical device or VM.

IPSec / L2TP

Device Support, native drivers:
macOS Sierra (10.12)
macOS High Sierra (10.13)
iOS 9
iOS 10


Perform a normal OpenBSD 6.2 install and perform the steps below logged in as root.

The base install includes Packet Filter, IPsec and npppd, so no additional packages should be needed.

Set the hostname of the OpenBSD VPN server by editing `/etc/myname`. For details see

Finally, assign a static ip address, either through DHCP or by editing the appropriate `/etc/hostname.XXX` file.

Network and Firewall Configuration

The network details for this configuration are:

OpenBSD Server192.168.2.100
Private network192.168.2.0/24 (
DHCP / DNS / Firewall192.168.2.1
VPN network pool10.0.0.2-
VPN network gateway to private network10.0.0.1

Router and Firewall

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.

On small networks, often the DHCP, DNS and Firewall services are provided by the same gateway router.

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:

  1. Add static route from to access ip
  2. Forward UDP port 4500 to
  3. Forward UDP port 500 to

Configure `npppd`

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

All VPN users must be added 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=

NOTE: The `USER_SEEKRIT` is the password for the user `jappleseed`.

Configure IPsec

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.

Configure 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)

Configure `sysctl`

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

Configure `rc.conf.local`

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.


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


That is it, a little more complicated then a VPN appliance UI, but gives you complete control.

Listed below are how to setup a macOS and iOS 10 client.

macOS 10.13 High Sierra Client VPN

Here are the steps to setup an macOS 10.13 High 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, the status should be `Not Configured`
– In the right pane:
– `Server Address`, set to external IP address for the network (`XXX.XXX.XXX.XXX`) or domain name
– `Account Name`, set to username from npppd-users (`jappleseed`)

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

iOS 10 Client VPN

Here are the steps to setup an iOS 10 Client VPN:

– Open `` (the gear icon)
– Select `General`, `VPN`
– Select `Add VPN Configuration…`

– Set the `Type` to `L2TP`
– Set an appropriate description
– Set `Server` to external IP address for the network (`XXX.XXX.XXX.XXX`) or domain name
– Set `Account Name` to username from npppd-users (`jappleseed`)
– Set `Password` to password from npppd-users (`USER_SEEKRIT`), or leave empty to be prompted every time
– Set `Secret` to psk from ipsec.conf (`SHARED_SEEKRIT`)
– Tap `Done`

Comments are closed.