nguvu

pfSense remote access via OpenVPN

Revised 9 September 2017.

Introduction

A typical home setup may involve running many services which a user may want to gain access to when away from the home or office, security cameras, media collections and system minitoring tools for example. It is possible to open a myriad of firewall ports to provide remote access to all of your local services but exposing more than is absolutely necessary increases the risk of unauthorized intrusion. I provide a secure single VPN tunnel into my network which enables access to all my local services. This guide will build upon the previous pfSense baseline guides and demonstrate how to configure pfSense and an iOS device to enable access to internal servers remotely.

external DNS

Most consumer internet connections provide service via a dynamic IP address rather than a static one, to enable us to locate our network we need to setup a Dynamic DNS service in pfSense that can be updated with our local WAN address as and when it changes. There are a number of Dynamic DNS providers supported by pfSense, navigate to Services > DynamicDNS and open up the service type drop down to see the options.

I’ll use Amazons Route 53 for this guide. We will create a test DNS entry in Route53’s DNS service for access.nguvu.org which will be updated with my WAN address. Depending on which Dynamic DNS service you chose, your authorisation settings may be slightly different.

Dynamic DNS

Navigate to Services > Dynamic DNS

Route53 Dynamic DNS Setup
Route53 Dynamic DNS Setup

If everything is correct, your Dynamic DNS record should be updated to that of your WAN interface. We will use this record in our VPN tunnel connection settings later.

Route53 Dynamic DNS Configured
Route53 Dynamic DNS Configured

From the command line, perform a DNS lookup to verify the correct address is correctly being returned (I’ve obfuscated the Address response below)

$ nslookup access.nguvu.org
Server:         8.8.8.8
Address:        8.8.8.8#53

Non-authoritative answer:
Name:   access.nguvu.org
Address: 1.2.3.4

Create ‘roadwarrior’ certificate authority

To secure access to our SOHO network, we need to create a certificate authority to validate devices attempting to gain access.

Navigate to System > Cert Manager > CAs

Create / Edit CA

Internal Certificate Authority

Create internal certificate authority
Create internal certificate authority

Once created, verify your certificate authority looks like this when done

Internal certificate authority
Internal certificate authority

Create ‘roadwarrior’ certificate

Navigate to System > Cert Manager > Certificates

Select Create an internal certificate

Add a new certificate

Internal Certificate

Certificate Attributes

Save

Create roadwarrior certificate
Create roadwarrior certificate

Verify your certificate looks like this when done

Created roadwarrior certificate
Created roadwarrior certificate

Create a certificate revocation list

You’ll need a revocation list for if/when you need to expire any certificates you create. Although this isnt required to get our remote access working, its trivial to create so we may as well.

Navigate to System > Certificates > Certificate Revocation

Internal Certificate Revocation List

Create the OpenVPN server

Now we’ll create the OpenVPN server which remote devices will connect to. We will change from the default port of 1194 to 443 as this port is often closed on remote networks.

Navigate to VPN > OpenVPN > Server

Click +Add

General Information

Cryptographic settings

Tunnel Settings

Client Settings

Advanced Client Settings

Advanced Configuration

Create VPN Server
Create VPN Server

Assign OpenVPN interface

We can now create an interface based on the OpenVPN server we just created.

Navigate to Interfaces > Assign

Select ‘ovpns4 (Roadwarrior VPN)’
Click Add

Add VPN server interface
Add VPN server interface

Click on the OPTx interface next to Roadwarrior VPN Network port

once you’ve saved and applied the changes, your interface should look like this

VPN server interface
VPN server interface

Assign OpenVPN server routing

Navigate to System > Routing

Click ‘copy gateway’ icon next to RW_VPN_VPNV4 gateway

Configure VPN server gateway
Configure VPN server gateway

Set RW_VPN firewall rules

This section uses a few aliases which I used in my pfSense baseline configuration, please refer to that guide if this doesn’t make sense to you. Setup the rules on the OpenVPN server interface to allow for the following access

Navigate to Firewall > Rules and select RW_VPN

Allow Pings for network diagnostics

Allow traffic to local subnets (LOCAL_SUBNETS alias) on permitted ports only (Allowed_OUT_ports_LAN alias).

Pass approved internet bound traffic out the VPN gateway

Default Block & log IPv4

Block default IPv6

Your RW_VPN interface should look this this when done.

Configure VPN firewall rules
Configure VPN firewall rules

Allow OpenVPN access for the WAN port

We will now open a port on our firewall to allow access to the OpenVPN server which is running on port 443.

Navigate to Firewall > WAN

Select ↑Add

WAN firewall rules

Your WAN interface should look this this when done.

Configure WAN firewall rules
Configure WAN firewall rules

Allow DNS resolution

Navigate to Services > DNS Resolver

Under Network interfaces dropdown, add RW_VPN to the selection to enable DNS resolution for remote devices.

Save & Apply

Set up outgoing NAT for inbound VPN connection

NAT is needed to convert your inbound devices private local IP address (192.168.200.0/24) to the global registered address space. We’ll set this up for our multiple VPN_WAN gateways, if you are only using a single VPN gateway, you’ll only need one of these three rules.

Navigate to Firewall > NAT and select the Outbound tab

Create ‘RW_VPN to VPN_WAN` NAT

Click ↴Add

Create ‘RW_VPN to VPN2_WAN` NAT

Click ↴Add

Create ‘RW_VPN to VPN_WAN` NAT

Click ↴Add

Update aliases

I use the LOCAL_SUBNETS alias to define traffic which is internal and external. We need to add our new RW_VPN address range to this address to ensure we match traffic correctly against the appropriate firewall rules.

Navigate to Firewall > Aliases

Click the pencil icon next to the LOCAL_SUBNETS alias to edit the list

Add the RW_VPN address range, i.e

Click Save & Apply

Your LOCAL_SUBNETS alias should look this this when done.

Updated alias
Update alias

Create a client certificate

We will now create a client certificate for an iOS device. Although you can set OpenVPN up to accept the same certificate from multiple clients its a less secure solution and not my preferred option. This option allows you to specify a certificate per user or client and provides the ability to expire a single certificate to revoke access at any time.

Navigate to System > Cert Manager > Certificates

Click Add/Sign

Internal Certificate

Certificate Attributes

Your certificates summary should look this this when done.

iPhone certificate
iPhone certificate

Install OpenVPN Client Export wizard

We will use the Client Export Wizard to export client certificates. Navigate to System > Packages > Available packages and click Install next to the OpenVPN-client-export to install the utility.

You’ll see the window populate with a progress report…

>>> Installing pfSense-pkg-openvpn-client-export... 
Updating pfSense-core repository catalogue...
pfSense-core repository is up to date.
Updating pfSense repository catalogue...
pfSense repository is up to date.
All repositories are up to date.
The following 4 package(s) will be affected (of 0 checked):

New packages to be INSTALLED:
        pfSense-pkg-openvpn-client-export: 1.4.13_1 [pfSense]
        openvpn-client-export: 2.4.3_4 [pfSense]
        zip: 3.0_1 [pfSense]
        p7zip: 16.02 [pfSense]

Number of packages to be installed: 4

The process will require 18 MiB more space.
11 MiB to be downloaded.
[1/4] Fetching pfSense-pkg-openvpn-client-export-1.4.13_1.txz: ... done
[2/4] Fetching openvpn-client-export-2.4.3_4.txz: .......... done
[3/4] Fetching zip-3.0_1.txz: .......... done
[4/4] Fetching p7zip-16.02.txz: .......... done
Checking integrity... done (0 conflicting)
[1/4] Installing openvpn-client-export-2.4.3_4...
[1/4] Extracting openvpn-client-export-2.4.3_4: .......... done
[2/4] Installing zip-3.0_1...
[2/4] Extracting zip-3.0_1: .......... done
[3/4] Installing p7zip-16.02...
[3/4] Extracting p7zip-16.02: .......... done
[4/4] Installing pfSense-pkg-openvpn-client-export-1.4.13_1...
Extracting pfSense-pkg-openvpn-client-export-1.4.13_1: .......... done
Saving updated package information...
done.
Loading package configuration... done.
Configuring package components...
Loading package instructions...
Custom commands...
Writing configuration... done.
>>> Cleaning up cache... done.
Success

Export the certificate

Once the wizard has finished installing, navigate to VPN > OpenVPN and select Client Export and set up the options as follows:

OpenVPN Server

Client Connection Behavior

Certificate eport options

Proxy Options

Advanced

Save as default

There will now be several options displayed alongside each certificate for exporting in various formats. We will use the inline configuration for the OpenVPN Connect client.

Click on OpenVPN connect (Android or iOS)

A certificate file will be downloaded to your desktop which we can now transfer across to our iOS device.

Client software install

The OpenVPN connect application provides OpenVPN functionality for a number of platforms. Install this on your device to provide the means to process .ovpn files.

In terms of getting the .ovpn file to your device, there are numerous ways to handle this. You can email the file to yourself, transfer it via a cloud service such as Dropbox however please be aware that this file contains all the details needed to access your network and hence its worthwhile taking extra care in how you transfer it to prevent it being compromised. A few methods which provide a secure method include SpiderOak which is an encrypted Dropbox alternative, iTunes or my favourite, Instashare which facilitates direct transfers from Mac > iOS devices.

In my case, once I have dragged the .ovpn file to my instashare folder the file appears on my iOS device.

Instashare
Instashare

I can now copy the file into the OpenVPN Connect Application which will begin the import process

Instashare import
Instashare import

OpenVPN will open and prompt you to import the certificate. Click the green + symbol to add it to your device.

OpenVPN Connect import
OpenVPN Connect import

Once imported, you can toggle the connection switch to initiate an connection.

OpenVPN Connect
OpenVPN Connect

If everything has gone correctly, you should see the display change to connected with associated IP, port and protocol details below

OpenVPN connect
OpenVPN connected

You can debug any errors or validate the connection is correct by inspecting the log by expanding the Connected box with the ‘>’ arrow.

OpenVPN log
OpenVPN log

Here’s my log relating to this connection example for reference

2017-09-09 18:56:51 ----- OpenVPN Start -----
OpenVPN core 3.1.2 ios arm64 64-bit built on Dec  5 2016 12:50:25
2017-09-09 18:56:51 Frame=512/2048/512 mssfix-ctrl=1250
2017-09-09 18:56:51 UNUSED OPTIONS
0 [persist-tun]
1 [persist-key]
4 [tls-client]
7 [lport] [0]
8 [verify-x509-name] [Roadwarrior_cert] [name]

2017-09-09 18:56:51 EVENT: RESOLVE
2017-09-09 18:56:51 Contacting [xxxx:xxxx::xx:x:x:xxxx:xxx]:443 via UDP
2017-09-09 18:56:51 EVENT: WAIT
2017-09-09 18:56:51 SetTunnelSocket returned 1
2017-09-09 18:56:51 Connecting to [access.nguvu.org]:443 (2607:7700::1a:0:1:4c5b:9d7) via UDPv6
2017-09-09 18:56:52 EVENT: CONNECTING
2017-09-09 18:56:52 Tunnel Options:V4,dev-type tun,link-mtu 1558,tun-mtu 1500,proto UDPv4,comp-lzo,keydir 1,cipher AES-256-CBC,auth SHA1,keysize 256,tls-auth,key-method 2,tls-client
2017-09-09 18:56:52 Creds: UsernameEmpty/PasswordEmpty
2017-09-09 18:56:52 Peer Info:
IV_GUI_VER=net.openvpn.connect.ios 1.1.1-212
IV_VER=3.1.2
IV_PLAT=ios
IV_NCP=2
IV_TCPNL=1
IV_PROTO=2
IV_LZO=1
IV_AUTO_SESS=1

2017-09-09 18:56:52 VERIFY OK: depth=1
cert. version    : 3
serial number    : 00
issuer name      : C=US, ST=My State, L=My City, O=My org, emailAddress=info@nguvu.org, CN=internal-ca
subject name      : C=US, ST=My State, L=My City, O=My org, emailAddress=info@nguvu.org, CN=internal-ca
issued  on        : 2016-03-02 01:32:46
expires on        : 2026-02-28 01:32:46
signed using      : RSA with SHA-256
RSA key size      : 4096 bits
basic constraints : CA=true
key usage        : Key Cert Sign, CRL Sign

2017-09-09 18:56:52 VERIFY OK: depth=0
cert. version    : 3
serial number    : 02
issuer name      : C=US, ST=My State, L=My City, O=My org, emailAddress=info@nguvu.org, CN=internal-ca
subject name      : C=US, ST=My State, L=My City, O=My org, emailAddress=info@nguvu.org, CN=Roadwarrior_cert
issued  on        : 2016-03-02 02:08:49
expires on        : 2026-02-28 02:08:49
signed using      : RSA with SHA-256
RSA key size      : 4096 bits
basic constraints : CA=false
subject alt name  : pfsense.local.lan
cert. type        : SSL Server
key usage        : Digital Signature, Key Encipherment
ext key usage    : TLS Web Server Authentication, ???

2017-09-09 18:56:52 SSL Handshake: TLSv1.2/TLS-ECDHE-RSA-WITH-AES-256-GCM-SHA384
2017-09-09 18:56:52 Session is ACTIVE
2017-09-09 18:56:52 EVENT: GET_CONFIG
2017-09-09 18:56:52 Sending PUSH_REQUEST to server...
2017-09-09 18:56:52 OPTIONS:
0 [dhcp-option] [DOMAIN] [local.lan]
1 [dhcp-option] [DNS] [192.168.200.1]
2 [dhcp-option] [NTP] [192.168.200.1]
3 [redirect-gateway] [def1]
4 [comp-lzo] [adaptive]
5 [route-gateway] [192.168.200.1]
6 [topology] [subnet]
7 [ping] [10]
8 [ping-restart] [60]
9 [ifconfig] [192.168.200.2] [255.255.255.0]
10 [peer-id] [0]
11 [cipher] [AES-256-GCM]

2017-09-09 18:56:52 PROTOCOL OPTIONS:
  cipher: AES-256-GCM
  digest: SHA1
  compress: LZO
  peer ID: 0
2017-09-09 18:56:52 EVENT: ASSIGN_IP
2017-09-09 18:56:52 Unknown pushed DHCP option: [dhcp-option] [NTP] [192.168.200.1]
2017-09-09 18:56:52 TunPersist: saving tun context:
Session Name: access.nguvu.org
Layer: OSI_LAYER_3
Remote Address: xxxx:xxxx::xx:x:x:xxxx:xxx [IPv6]
Tunnel Addresses:
  192.168.200.2/24 -> 192.168.200.1
Reroute Gateway: IPv4=1 IPv6=0 flags=[ ENABLE REROUTE_GW DEF1 IPv4 ]
Block IPv6: no
Add Routes:
Exclude Routes:
DNS Servers:
  192.168.200.1
Search Domains:
  local.lan

2017-09-09 18:56:52 Connected via tun
2017-09-09 18:56:52 LZO-ASYM init swap=0 asym=0
2017-09-09 18:56:52 EVENT: CONNECTED @access.nguvu.org:443 (xxxx:xxxx::xx:x:x:xxxx:xxx) via /UDPv6 on tun/192.168.200.2/ gw=[192.168.200.1/]
2017-09-09 18:56:52 SetStatus Connected
2017-09-09 18:56:53 NET Internet:ReachableViaWWAN/WR t------

Verification of functionality and performance

Navigate to Status > OpenVPN

Verify the OpenVPN tunnel is connected as expected

OpenVPN connections
OpenVPN connections

Expiring keys

At some stage you will want to expire a certificate.

Navigate to System > Cert Manager > Cert Revocation

Select the certificate you want to expire, and a reason why and select ‘Add’

OpenVPN certificate revocation
OpenVPN certificate revocation

The certificate will now be revoked and access denied. It is possible to reinstall the certificate by deleting the revocation with the blue ‘x’ on the right of the screen.

Changelog

15 January 2018
Fixed error in certificate export instruction
Fixed typos

2 November 2017
Fixed roadwarrior certificate server type error
Fixed RW_VPN NAT section