Strongswan IPSec Mediation – Both Ubuntu Linux 20.04 Peers Behind Cisco NAT

Background

Strongswan is an open source project that implements the IKE protocol which is used for cryptographic key negotiation in the IPSec standard protocol. IPSec is used to build an encrypted network connection between two points on a network, usually the Internet but not always.

Most often, the two points where the encryption and decryption are happening know about each other’s IP address, on the Internet that means they have publicly routable IP addresses. IPSec has a built-in mechanism to handle the scenario if one of these points does not have an a public routable IP address, this is called NAT-Traversal. It looks something like this:

POINT A —> NAT ROUTER —> INTERNET —> POINT B

Point A must initiate the connection to Point B because it has a private IP address (10.x and the like) and that’s the only way the NAT router will let the connection through.

But what if BOTH peers are behind NAT routers with private IP addresses? Something like this:

POINT A —> NAT ROUTER —> INTERNET —> NAT ROUTER —> POINT B

Private-peer-to-private-peer connectivity is established in other network protocols such as VoIP using some sort of 3rd party mediator that performs a trick called UDP hole-punching, where both peers are told by the mediator the public IP address of the NAT Router that is in front of the peer they are trying to connect to. For VoIP this is usually a STUN server. Both peers attempt a connection at the same time, the NAT Routers write translations for the peers, and a connection is built.

While this technique is pretty ancient and many applications implement it, there is not a standard way to do it for IPSec. Strongswan, it seems, has a little known feature for IPSec peer mediation that allows for peer to peer NAT Traversal similar to STUN in VoIP. This feature requires that a third device have a public IP (can’t escape a public IP somewhere in the equation) and running the Strongswan mediation service. It only works with strongswan, although an RFC draft was created back in 2008 in the hopes that mediation for IPSec would be standardized.

Topology

The two Ubuntu 20.04 IPSec peers are both behind Cisco IOSv routers running a basic NAT in Port Address Translation (PAT) mode, which is a tcp/udp port-based one-to-many NAT that is running by default on many consumer routers and is the way the many devices today connect to the Internet. In other words, 192.168.0.3 can not ping 172.16.0.3, and vice versa. But they can both ping 13.0.0.2, where our secret weapon is located, the Strongswan IKE Mediator.

Installation

Installing Strongswan on Ubuntu 20.04 is easy as pie:

apt-get install strongswan

Configuration

UbuntuServer20.04-1

First edit /etc/ipsec.conf

config setup
conn %default
        ikelifetime=60m
        keylife=20m
        rekeymargin=3m
        keyingtries=1
        keyexchange=ikev2
        mobike=no
        dpdaction=restart
        dpddelay=60s
        left=%defaultroute
        leftfirewall=yes

conn medsrv
        leftid=bob@questioncomputer.com
        leftauth=psk
        right=13.0.0.2
        rightid=mediator@questioncomputer.com
        rightauth=psk
        mediation=yes
        authby=secret
        auto=start

conn peer
        leftid=bob@questioncomputer.com
        leftauth=psk
        leftsubnet=192.168.0.0/24
        right=%any
        rightid=alice@questioncomputer.com
        rightsubnet=172.16.0.0/24
        rightauth=psk
        authby=secret
        mediated_by=medsrv
        auto=start

Then edit /etc/ipsec.secrets to put your PSK in there:

mediator@questioncomputer.com : PSK "james"
bob@questioncomputer.com : PSK "james"
alice@questioncomputer.com : PSK "james"

UbuntuServer20.04-2

First edit /etc/ipsec.conf

conn %default
        ikelifetime=60m
        keylife=20m
        rekeymargin=3m
        keyingtries=1
        keyexchange=ikev2
        mobike=no
        dpdaction=restart
        dpddelay=60s
        left=%defaultroute
        leftfirewall=yes
conn medsrv
        leftid=alice@questioncomputer.com
        leftauth=psk
        right=13.0.0.2
        rightid=mediator@questioncomputer.com
        rightauth=psk
        mediation=yes
        auto=add

conn peer
        leftid=alice@questioncomputer.com
        leftauth=psk
        leftsubnet=172.16.0.0/24
        right=%any
        rightid=bob@questioncomputer.com
        rightsubnet=192.168.0.0/24
        rightauth=psk
        mediated_by=medsrv
        authby=secret
        auto=start

Then edit /etc/ipsec.secrets to put your PSK in there:

mediator@questioncomputer.com : PSK "james"
bob@questioncomputer.com : PSK "james"
alice@questioncomputer.com : PSK "james"

Mediator (UbuntuServer20.04-4)

First edit /etc/ipsec.conf

conn %default
        ikelifetime=60m
        keylife=20m
        rekeymargin=3m
        keyingtries=1
        keyexchange=ikev2
        mobike=no
        dpdaction=clear
        dpddelay=60s

conn medsrv
        left=13.0.0.2
        leftid=mediator@questioncomputer.com
        leftauth=psk
        leftfirewall=yes
        right=%any
        rightauth=psk
        mediation=yes
        authby=secret
        auto=add

Then edit /etc/ipsec.secrets

mediator@questioncomputer.com : PSK "james"<br>bob@questioncomputer.com : PSK "james"<br>alice@questioncomputer.com : PSK "james"

Make sure to issue this on all three to load your configs:

ipsec restart

Verification

A healthy connection can be checked with the ‘ipsec’ command:

root@u2004:/home/james/strongswan# ipsec statusall
Status of IKE charon daemon (strongSwan 5.9.0, Linux 5.4.0-29-generic, x86_64):
  uptime: 103 minutes, since Oct 08 19:38:24 2020
  malloc: sbrk 1748992, mmap 0, used 902656, free 846336
  worker threads: 11 of 16 idle, 5/0/0/0 working, job queue: 0/0/0/0, scheduled: 14
  loaded plugins: charon agent connmark eap-mschapv2 aes des rc2 sha2 sha3 sha1 md5 mgf1 random nonce x509 revocation constraints pubkey pkcs1 pkcs7 pkcs8 pkcs12 pgp dnskey sshkey pem openssl fips-prf gmp curve25519 chapoly xcbc cmac hmac gcm drbg attr kernel-netlink resolve socket-default socket-dynamic stroke vici updown xauth-generic lookip error-notify addrblock unity counters
Listening IP addresses:
  192.168.0.3
Connections:
      medsrv:  %any...13.0.0.2  IKEv2, dpddelay=60s
      medsrv:   local:  [left@questioncomputer.com] uses pre-shared key authentication
      medsrv:   remote: [mediator@questioncomputer.com] uses pre-shared key authentication
      medsrv:   child:  dynamic === dynamic TUNNEL, dpdaction=restart
        peer:  %any...%any  IKEv2, dpddelay=60s
        peer:   local:  [left@questioncomputer.com] uses pre-shared key authentication
        peer:   remote: [right@questioncomputer.com] uses pre-shared key authentication
        peer:   child:  192.168.0.0/24 === 172.16.0.0/24 TUNNEL, dpdaction=restart
Security Associations (2 up, 0 connecting):
        peer[6]: ESTABLISHED 2 minutes ago, 192.168.0.3[left@questioncomputer.com]...12.0.0.2[right@questioncomputer.com]
        peer[6]: IKEv2 SPIs: 400da3c783ad093d_i 35869903e6803225_r*, pre-shared key reauthentication in 52 minutes
        peer[6]: IKE proposal: AES_CBC_128/HMAC_SHA2_256_128/PRF_HMAC_SHA2_256/ECP_256
        peer{10}:  INSTALLED, TUNNEL, reqid 1, ESP in UDP SPIs: c01b6c68_i c56e26d5_o
        peer{10}:  AES_CBC_128/HMAC_SHA2_256_128, 0 bytes_i, 0 bytes_o, rekeying in 12 minutes
        peer{10}:   192.168.0.0/24 === 172.16.0.0/24
      medsrv[3]: ESTABLISHED 49 minutes ago, 192.168.0.3[left@questioncomputer.com]...13.0.0.2[mediator@questioncomputer.com]
      medsrv[3]: IKEv2 SPIs: 127a15068a32e07f_i* 703cba84aa11f49e_r, pre-shared key reauthentication in 2 minutes
      medsrv[3]: IKE proposal: AES_CBC_128/HMAC_SHA2_256_128/PRF_HMAC_SHA2_256/ECP_256

You’ll be looking to see that both the “medsrv” and “peer” connections are in an “Established” state.

And of course as always, make sure you ping across the tunnel to make sure it works.

As an added bonus, I was able to ping through the tunnel from l92.168.0.3 to the Cisco NAT Router at 172.16.0.1, I just need to add a route on the Cisco NAT Router by issuing “ip route 192.168.0.0 255.255.255.0 172.16.0.3”.

Troubleshooting

The log file where most logs go in Ubuntu is at ‘/var/log/syslog’, grepping for “charon” will help you sort them:

root@u2004:/home/james/strongswan# tail /var/log/syslog | grep charon
Oct  8 21:28:41 u2004 charon: 13[NET] sending packet: from 192.168.0.3[4500] to 12.0.0.2[4500] (80 bytes)
Oct  8 21:28:41 u2004 charon: 16[NET] received packet: from 12.0.0.2[4500] to 192.168.0.3[4500] (80 bytes)
Oct  8 21:28:41 u2004 charon: 16[ENC] parsed INFORMATIONAL response 8 [ ]

And as usual, do a packet capture to see if the two peers are trying to build a connection to each other. If packets are not being generated or dropped somewhere, you’ll know where to look for a problem. You can filter for “isakmp” packets to narrow things down:

In the above image you can see there is a connection between the NAT routers 11.0.0.2 and 12.0.0.2, but also connections to the mediator at 13.0.0.2.