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.
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.
Requirements
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.
VPN:
IPSec / L2TP
Device Support, native drivers:
OSX El Capitan (10.11), Sierra (10.12)
iOS 9, 10
OpenBSD
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: 192.168.2.100
– Private network: 192.168.2.0/24 (192.168.2.0-192.168.2.254)
– DHCP / DNS / Firewall: 192.168.2.1
– VPN network pool: 10.0.0.2-10.0.0.254
– VPN network gateway to private network: 10.0.0.1
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 10.0.0.0 to access ip 192.168.2.100
– Forward UDP port 4500 to 192.168.2.100
– Forward UDP port 500 to 192.168.2.100
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 (192.168.2.1 in this example) make the following changes:
|
1 |
sudo vi /etc/npppd/npppd.conf |
|
1 2 3 4 5 6 |
ipcp IPCP { pool-address 10.0.0.2-10.0.0.254 # CHANGED #dns-servers 8.8.8.8 dns-servers 192.168.2.1 } |
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:
|
1 |
sudo vi /etc/npppd/npppd-users |
|
1 2 3 4 5 6 7 8 9 10 11 12 |
# $OpenBSD: npppd-users,v 1.1 2012/09/20 12:51:43 yasuoka Exp $ # sample npppd-users file. see npppd-users(5) #taro:\ # :password=taro's password:\ # :framed-ip-address=10.0.0.101: #hana:\ # :password=hana's password:\ # :framed-ip-address=10.0.0.102: # ADDED jappleseed:\ :password=USER_SEEKRIT: |
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:
|
1 |
sudo vi /etc/ipsec.conf |
|
1 2 3 4 5 6 7 |
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 \ psk "SHARED_SEEKRIT" |
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:
|
1 2 |
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:
|
1 |
sudo vi /etc/pf.conf |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
# $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 # BEGIN ADDED # 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) # END ADDED |
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:
|
1 |
sudo vi /etc/sysctl.conf |
|
1 2 3 4 |
# BEGIN ADDED net.inet.ip.forwarding=1 net.pipex.enable=1 # END ADDED |
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 :
|
1 |
sudo vi /etc/rc.conf.local |
|
1 2 3 |
isakmpd_flags="-K" ipsec=YES npppd_flags="" |
Reboot the OpenBSD server.
Conclusion
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)
Management
Monitoring different interfaces:
|
1 2 3 |
sudo tcpdump -ni enc0 sudo tcpdump -ni pppx0 sudo tcpdump -ni pflog0 |
To monitor npppd vpn sessions use npppctl:
|
1 |
npppctl session all |
To monitor ipsec use ipsecctl:
|
1 |
sudo ipsecctl -s all |
View sysctl settings:
|
1 2 |
sysctl net.inet.ip.forwarding sysctl net.pipex.enable |
Display all routing tables:
|
1 |
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.
December 12th, 2016 at 11:55 pm
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? :^)
Cheers,
rjc
December 14th, 2016 at 8:00 am
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? 🙂
December 17th, 2016 at 9:08 am
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 :^)