Friday, September 8, 2017

Fast IPSec on Embedded Devices With CHACHA20-POLY1305

tl;dr: IPSec at ~400 Mbps on a CPU with no hardware crypto acceleration.

My DIY switch/firewall has an Intel Celeron J1900. While it's quite fast at forwarding/routing packets (>1Gbps tested/confirmed, likely actual ~3.6 Gbps), it can barely do 25 Mbps with strongSwan's defaults. The main reason is that it's lacking AES-NI, or any hardware crypto accelerator.

I'm assuming you've already used strongSwan before or have read another tutorial. Only extra software dependency for Ubuntu 16.04 is:

sudo apt-get install libstrongswan-extra-plugins

Config

/etc/ipsec.conf (intel.example.com)

config setup
        uniqueids=yes
        charondebug="ike 1, knl 1, cfg 1, net 1, esp 1, dmn 1,  mgr 1"

conn %default
        fragmentation=yes
        rekey=yes
        dpdaction=clear
        keyingtries=%forever
        keyexchange=ikev2
        compress=no
        dpddelay=600s

        # IKEv2 speed isn't a problem.
        ike=aes128gcm16-prfsha512-ecp521!

        # I'm not sure if ecp192 is the best choice, ask a real crypto person for verification.
        esp=chacha20poly1305-ecp192!

        authby=secret

conn pulse
        # Due to peering, these two ISPs are faster to connect via IPv4 =( 
        left=%any4
        [email protected]
        leftauth=secret
        # 2001:db8:200::/40 == Random IPv6 address. Not really needed here.
        # 10.10.10.10/32 == Random private IPv4 address.
        # 2001:db8:ff00:16b::/64 == All of our public addresses that we want to tunnel instead.

        leftsourceip=2001:db8:200::,10.10.10.10
        leftsubnet=2001:db8:100::/40,10.10.10.10/32,2001:db8:ff00:16b::/64

        right=pulse.example.com
        [email protected]
        rightauth=secret

        rightsubnet=2001:db8:ff00::/40,203.0.113.0/20,10.137.144.17/16
        # 2001:db8:ff00::/40 ==  All of their IPv6 public addresses that we want to tunnel.
        # 203.0.113.0/20 == Their public IPv4 network
        # 10.137.144.17/16 == Their private IPv4 network.

        auto=start

/etc/ipsec.conf (pulse.example.com)

config setup
        uniqueids=yes
        charondebug="ike 1, knl 1, cfg 1, net 1, esp 1, dmn 1,  mgr 1"

conn %default
        fragmentation=yes
        rekey=yes
        dpdaction=clear
        keyingtries=%forever
        keyexchange=ikev2
        # compress=no
        dpddelay=60s
        authby=secret

conn intel
        left=2001:db8:ff00::1,203.0.113.0
        [email protected]
        leftauth=secret
        leftsubnet=2001:db8:ff00::/40,203.0.113.0/20,10.137.144.17/16

        [email protected]
        rightauth=secret
        rightsourceip=10.10.10.10,2001:db8:200::
        rightsubnet=2001:db8:100::/40,10.10.10.10/32,2001:db8:ff00:16b::/64

        ike=aes128gcm16-prfsha512-ecp521!
        esp=chacha20poly1305-ecp192!

        compress=no
        dpddelay=600s

        auto=add

/etc/ipsec.secrets (intel.example.com)

@intel.example.com @pulse.example.com : PSK "Nj3eOavMxgXQX3gA1mPXy"

/etc/ipsec.secrets (pulse.examples.com)

@pulse.example.com @intel.example.com : PSK "Nj3eOavMxgXQX3gA1mPXy"

/etc/strongswan.conf (both)

We have to send the vendor ID because of CHACHA20-POLY1305.

charon {
        load_modular = yes
        plugins {
                include strongswan.d/charon/*.conf
        }
        send_vendor_id = yes
}

include strongswan.d/*.conf

Parallelizing (intel.example.com)

First, make sure you do have kernel support for chacha20.

dave@intel:~$ grep -E 'driver.*chacha20' /proc/crypto
driver       : seqiv(rfc7539esp(chacha20-simd,poly1305-simd))
driver       : rfc7539esp(chacha20-simd,poly1305-simd)
driver       : chacha20-simd
driver       : chacha20-simd
driver       : chacha20-generic

Looks good! You'll see an error message, but don't worry, it actually worked.

dave@intel:~$ sudo modprobe tcrypt alg="pcrypt(rfc7539esp(chacha20,poly1305))" type=3
modprobe: ERROR: could not insert 'tcrypt': Unknown symbol in module, or unknown parameter (see dmesg)
dave@intel:~$ grep -E 'driver.*pcrypt.*chacha20' /proc/crypto
driver       : pcrypt(pcrypt(rfc7539esp(chacha20-simd,poly1305-simd)))
driver       : pcrypt(rfc7539esp(chacha20-simd,poly1305-simd))

Parallelizing (pulse.example.com)

We're not going to enable pcrypt on pulse.example.com, since it's a single thread VM.

Testing

Run sudo systemctl restart strongswan.service on both machines first to make sure the changes have been loaded.

dave@pulse:~$ while sleep 1s; do iperf3 -s -B 2001:db8:ff00::1; done
dave@intel:~$ iperf3 -c 2001:db8:ff00::1 -R -Z -t 120 -P 128 -O 60 -B 2001:db8:100::
....
[SUM]   0.00-119.97 sec  5.60 GBytes   401 Mbits/sec  149461             sender
[SUM]   0.00-119.97 sec  5.60 GBytes   401 Mbits/sec                  receiver

iperf Done.


TODO: Get this up to >750Mbps.

Update #1: Not sure why, but I'm getting quite a bit of packet loss compared to AES128.

No comments:

Post a Comment