Linux IPSEC using strongswan

Recently I took a look at some techniques I always wanted to take a look at. IPSEC for example is one of those techniques. Remembering how long it took my work-colleague to setup an ipsec connection I thought this would be a nightmare. Took him a few days to get a working ipsec connection to a customer appliance – seems that had nothing to do with ipsec. The horrible part was the documentation or rather the lack of proper documentation for that specific Peplink appliance. Anyway, here’s how you can setup ipsec pretty simple and fast.

Security / Authentication
First of all, let’s have a talk about security. I think the security recommendations cover this really well. Basically you’ve got a few options to setup authentication. I do believe that using pre-shared-keys is insecure and hence I do prefer the use of ECDSA keys.

The first step in setting everything up is creating ECDSA keys on every machine. You can do so like this:

openssl ecparam -genkey -name secp384r1 -noout -out HOSTNAME.priv.key

Obviously replace HOSTNAME with a name that suits you. The above creates the private key. The public key can be generated like this:

openssl ec -in HOSTNAME.priv.key -pubout -out HOSTNAME.pub.key

On all machines you’ve end up with a key-pair (private&public). Move the private key of the specific local machine to /etc/ipsec.d/private/ and copy the public keys from all hosts to /etc/ipsec.d/public (which you have to create). So in case you have three nodes it would look like so:

  • node1
    • /etc/ipsec.d/private/node1.priv.key
    • /etc/ipsec.d/public/node1.pub.key
    • /etc/ipsec.d/public/node2.pub.key
    • /etc/ipsec.d/public/node3.pub.key
  • node2
    • /etc/ipsec.d/private/node2.priv.key
    • /etc/ipsec.d/public/node1.pub.key
    • /etc/ipsec.d/public/node2.pub.key
    • /etc/ipsec.d/public/node3.pub.key
  • node3
    • /etc/ipsec.d/private/node3.priv.key
    • /etc/ipsec.d/public/node1.pub.key
    • /etc/ipsec.d/public/node2.pub.key
    • /etc/ipsec.d/public/node3.pub.key

In your /etc/ipsec.secrets you’ll have to tell it where to find the specific private key. So on node1 you’d use:

X.X.X.X : ECDSA "/etc/ipsec.d/private/node1.priv.key"

Replace X.X.X.X with the IP of the specific node and do the same on all nodes.

Configuration

Let’s edit /etc/ipsec.conf now. I truncate that file and add the following:

# ipsec.conf - strongSwan IPsec configuration file
 
conn general
    authby=ecdsasig
    compress=yes
    type=transport
    auto=start
    left=
    leftsigkey=
 
include /etc/ipsec.d/*.conf

The section „conn general“ is there to be included using „also=“ in other conn’s. Using authby=ecdsasig we just tell strongswan that it should use ECDSA to authenticate. Using compress=yes we tell it that it should prefer and offer compression. type=transport is the way we’ll start this set up. It defines a host-to-host connection. auto=start just tells strongswan to automatically start the connection when strongswan starts.

The interesting part is leftsigkey= and left=. leftsigkey should point to the public key of the local machine. For left= you’ll have to enter your local (it might be and in my case is, a public ip) address. I always use the local ip as left side. You might as well remove left= and leftsigkey= from conn general and define it in the specific host configuration file later.

You’ll have to create one host configuration file for every host on every host now. Assuming you’ve got node1, node2 and node3 you’ll need:

  • node1
    • /etc/ipsec.d/node2.conf
    • /etc/ipsec.d/node3.conf
  • node2
    • /etc/ipsec.d/node1.conf
    • /etc/ipsec.d/node3.conf
  • node3
    • /etc/ipsec.d/node1.conf
    • /etc/ipsec.d/node2.conf

Each of these configuration files would look similar to this:

conn node3-node1
  also=general
  # enter the ip of node1
  right=x.x.x.x
  rightsigkey=/etc/ipsec.d/public/node1.pub.key

So, just to make sure, on node3 the configuration file node2.conf would look like this:

conn node3-node2
  also=general
  # enter the ip of node2
  right=x.x.x.x
  rightsigkey=/etc/ipsec.d/public/node2.pub.key

Once done, restart ipsec on all nodes.

Verification

Check the logs:

root@janice:/etc# grep "CHILD_SA.*established" /var/log/syslog
Feb 18 17:06:13 janice charon: 09[IKE] CHILD_SA janice-nyota{3} established
                with SPIs xxx and TS xx.xxx.xxx.x/32 === xxx.xx.xxx.xxx/32 
Feb 18 17:07:12 janice charon: 15[IKE] CHILD_SA janice-christine{4} established
                with SPIs xxx and TS xx.xxx.xxx.x/32 === xxx.xx.xxx.xxx/32

In this case, janice is node1, nyota is node2 and christine is node3. You can see that according to the log file it established the transport so it should work. Shouldn’t it? Let’s check.

On node1 start

tcpdump -n -e -vv "esp && (src xx.xx.xx.xx)"

and replace xx.xx.xx.xx with the IP of node2. On node2 start a ping to node1.

17:23:41.018076 xx:xx:xx:xx:xx:xx > yy:yy:yy:yy:yy:yy, ethertype IPv4 (0x0800), length 150:
    (tos 0x0, ttl 59, id 14210, offset 0, flags [DF], proto ESP (50), length 136)
    xx.xx.xx.xx > yy.yy.yy.yy: ESP(spi=0xxxxxx,seq=0x5), length 116

The interesting part in here is the ESP stuff, which basically shows that it does indeed work. Also, you should see an increase in latency:

ipsec enabled

10 packets transmitted, 10 received, 0% packet loss, time 9014ms
rtt min/avg/max/mdev = 1.767/1.846/1.926/0.075 ms

ipsec disabled

10 packets transmitted, 10 received, 0% packet loss, time 9009ms
rtt min/avg/max/mdev = 0.889/0.960/1.009/0.053 ms

So IPSEC doubled the latency. Whether that is acceptable for you I do not know. It will also depend a lot on your hardware and the used ciphers. Compression might play a role, as well. Lots of stuff you can tune.

1 Comment

  • Alexander Velkov

    25. April 2017 at 15:06 Antworten

    Thank you Jean! You’re post helped me a lot!

Post a Comment