A look at algo VPN and pfSense NAT - beyond double-NAT and fragmentation

ansible
mobile
vpn
ipsec
Tags: #<Tag:0x00007fbc55b685c8> #<Tag:0x00007fbc55b68460> #<Tag:0x00007fbc55b68320> #<Tag:0x00007fbc55b681b8>

#1

algo VPN is IPsec based

Do you know the Cisco AnyConnect client? The one, which issues profiles to clients based on client routes? – Routes, that you can add with local admin privileges? Sure you do.
Besides this, the client is clunky and gets deployed via Java.

You know the Sophos UTM Home Edition {2}? It comes with all kinds of options for VPNs, including IPsec (like Algo, but more on that later), OpenVPN SSL / TLS VPN, HTML5 VPN (like “Zero Trust”), PPTP and so on. It can be setup to be compatible to the AnyConnect client. But that’s not a must. A browser may be enough; for some services.

So why algo?

algo is an OpenSource IPsec VPN stack, which is quite handy. The stack has a couple of features, which distinguish it from others:

  • Mobile support (iOS, Android) & Ad-Blocking (with lists)
    • on Android is can use Wireguard {1}, which is a modern VPN protocol as well
    • on iOS is generates .mobileconfig files for WiFi and cellular networks
  • on Mac OS X it works without a client (unlike OpenVPN)
  • you can use a dnscrypt proxy, that may use Cloudflare’s DNS (via dnsmasq)

If you don’t want the Ad-Blocking, the UTM might have features you want like:

  • Multi-Factor Authentication (interactive)
  • Out of the box setup (Web UI)
  • Logging (Syslog, Dashboards)
  • User Profiles with Network ACLs
  • HTML5 VPN (RDP, VNC, Web)

Test results

I have moved my current IPsec VPN setup to algo, because I want a VPN host with analysis utilities (tcpdump, sslstrip, tshark …).

My test results are positive for:

  • iOS 11.4
  • Android 7.1.1 (BlackBerry + Wireguard App)
  • Windows 10 Enterprise
  • Ubuntu 16.04 LTS (desktop)
  • Arch Linux

Let’s dive into some details, shall we?

References

{1} Wireguard is a simple VPN with advanced cryptography
{2} Sophos UTM

Double NAT and IP fragmentation

The lab system here is a small-scale VM: 1 vCPU, 1 GB RAM, 16 GB disk. The service is based on strongSwan {1} (charon) and dnsmasq with the dnscrypt-proxy.

We could actually use less RAM.

[email protected]:~$ sudo !!
sudo python ps_mem.py 
 Private  +   Shared  =  RAM used	Program
  2.8 MiB + 611.5 KiB =   3.3 MiB	charon
 11.0 MiB + 140.0 KiB =  11.1 MiB	dnsmasq
 15.6 MiB +  53.5 KiB =  15.6 MiB	dnscrypt-proxy

The IPsec service stack gets deployed by a helper utility (algo), that uses ansible (with Python).

The internal IP of the algo VM is within 192.168.1.0/24:

[email protected]:~$ ifconfig ens160
ens160    Link encap:Ethernet  HWaddr 00:0c:29:c9:a0  
          inet addr:192.168.1.Y  Bcast:192.168.1.255  Mask:255.255.255.0

This is NATed out with pfSense (more on that below). I use an MTU of 1514 on the VM host and of 1500 within the VM guest.

more configs/144.76.153.X/ipsec_marius.conf 
conn ikev2-144.76.153.X
    fragmentation=yes
    rekey=no
    dpdaction=clear
    keyexchange=ikev2
    compress=no
    dpddelay=35s

With certain double-NAT setups you may run into fragmentation issues. You can set fragmentation=no here. That is something that heavily depends on your virtual network stack. In this case I can use fragmentation; on cellular networks as well.

Here is the pfSense NAT config:

It passes …

  • UDP port 500 (ISAKMP)
  • UDP port 4500 (IPsec NAT-T)
  • UDP 51820 (Wireguard)

… to the 192.168.1.0/24 address, that’s used internally. pfSense runs the DHCP client for the VMs in that segment. algo runs a DHCP server for the VPN clients only. This should not mix.

Last but not least, let’s return to the algo host and enumerate the respective UDP services:

[email protected]:~/Source/algo$ sudo netstat -tulpen
    udp        0      0 0.0.0.0:4500            0.0.0.0:*                           0          17127       1400/charon     
    udp        0      0 0.0.0.0:500             0.0.0.0:*                           0          17126       1400/charon 
    udp        0      0 0.0.0.0:51820           0.0.0.0:*                           0          15914       -     

This indicates to me that the required services are NATed out and can be reached from the clients.

Results:

  • an OpenSource IPsec VPN for mobile and desktop clients on a VM
  • we are less dependant on VPN Apps or VPN clients
  • Ad-Blocking for mobiles (iPhone, iPad, Android)
  • IPsec NAT with pfSense as a gateway (double-NAT)
  • Wireguard on Android

TL;DR: simple, functional and flexible IPsec VPN for every client. Lower resource footprint than the UTM, and probably easier to handle from a command-line.

Future work

I am looking into Pritunl Zero for a setup that is more resistant against technical restrictiveness of international ISPs (China, O2 Germany, Airport WiFi…) and easier to handle with a mobile (bookmark).
Sophos UTM HTML5 Web VPN does not work with services like Splunk, Kibana, QRadar or Jupyter. Besides that I can reuse the algo VM I created here for both approaches.

References

{1} IKE keyring daemon charon


The Zero-Trust proxy hype - can we reverse-proxify everything and ditch VPNs?