Easy(ish) IPSec VPN with Shared ECDSA Certificates for Host to Host Connections

Let me start off by saying that using certificates for your IPSec VPNs adds another layer of complexity onto your connections. However what I’ve tried to do is to make this how to guide as easy to follow as I possibly can.

By using certificates we can negate the requirements to use pre shared keys and thus are considered more secure and if we have lots of tunnels it means we don’t have to worry about having a separate key for each connection therefore providing a great deal of scalability.

Please note that the authentication is based on the name in --san and on having a shared CA. I appreciate that the pki commands may look confusing at first, but you should be able to tailor them accordingly if you’re careful.  I appreciate that there is a lot of work to get this working, and this work represents a great deal more time than doing a usual PSK IPsec but it’ll be worth it in the end.

I will assume that your network looks like the following, and that you want to have encrypted connections between Ubuntu-Red and Ubuntu-Blue, and that Ubuntu-Gold is a separate server we are using just for the PKI and certificates.  We will be using Stronswan and Ubuntu 14.04 for this tutorial and I am also assuming you’ll want to use the far more secure EC certificates as opposed to the default RSA ones.

192.168.145.130 ubuntu-red
192.168.145.131 ubuntu-blue
192.168.145.132 ubuntu-gold

Install Strongswan on all Servers

Firstly you’ll want to run the following command on ALL the servers:

apt-get install strongswan-starter

This sets up the various directories we will use later on.

Setup the CA on ubuntu-gold

Now we need to create our CA certificate which we shall use to produce the certificates for our IPSec VPN.

The line below creates our private ECDSA key for signing the certificates we will be using.

ipsec pki --gen --type ecdsa --size 256 > /etc/ipsec.d/private/caKey.key

The next command creates the public certificate for our certificate authority.

ipsec pki --self --ca --in /etc/ipsec.d/private/caKey.key --type ecdsa --digest sha512 --outform pem --dn "C=US, O=IPSec VPN, CN=IPSec VPN Certificate Authority" > /etc/ipsec.d/cacerts/caCert.cer

Create the Client Certificates on ubuntu-gold

The following commands create the private keys for both of our servers.

ipsec pki --gen --type ecdsa --size 256 > /etc/ipsec.d/private/ubuntu-red.key
ipsec pki --gen --type ecdsa --size 256 > /etc/ipsec.d/private/ubuntu-blue.key

The following commands let us create certficates based on those keys we’ve just created.  Please note if you want to use your own IDs and naming conventions you’ll have to change the CN and --san elements.

ipsec pki --pub --type ecdsa --in /etc/ipsec.d/private/ubuntu-red.key | ipsec pki --issue --outform pem --digest sha512 --cacert /etc/ipsec.d/cacerts/caCert.cer --cakey /etc/ipsec.d/private/caKey.key --dn "C=US, O=IPSec VPN, CN=ubuntu-red" --san ubuntu-red > /etc/ipsec.d/certs/ubuntu-red.cer
ipsec pki --pub --type ecdsa --in /etc/ipsec.d/private/ubuntu-blue.key | ipsec pki --issue --outform pem --digest sha512 --cacert /etc/ipsec.d/cacerts/caCert.cer --cakey /etc/ipsec.d/private/caKey.key --dn "C=US, O=IPSec VPN, CN=ubuntu-blue" --san ubuntu-blue > /etc/ipsec.d/certs/ubuntu-blue.cer

Push the Client Certificates to the Servers from ubuntu-gold, you’ll need to type in the root password for each host.

scp /etc/ipsec.d/cacerts/caCert.cer [email protected]:/etc/ipsec.d/cacerts
scp /etc/ipsec.d/private/ubuntu-red.key [email protected]:/etc/ipsec.d/private
scp /etc/ipsec.d/certs/ubuntu-red.cer [email protected]:/etc/ipsec.d/certs
scp /etc/ipsec.d/cacerts/caCert.cer [email protected]:/etc/ipsec.d/cacerts
scp /etc/ipsec.d/private/ubuntu-blue.key [email protected]:/etc/ipsec.d/private
scp /etc/ipsec.d/certs/ubuntu-blue.cer [email protected]:/etc/ipsec.d/certs

Setup the Host to Host VPN on ubuntu-red

Edit the default ipsec.conf file:

nano /etc/ipsec.conf

Add the following to the bottom of the file:

conn red-to-blue
    authby=pubkey
    auto=route
    [email protected]
    leftcert=ubuntu-red.cer
    right=192.168.145.131
    [email protected]
    type=transport
    mobike=no

Save and close that file with [ctrl]+o and [ctrl]+x.

Now open the ipsec.secrets file:

nano /etc/ipsec.secrets

And add the following:

: ECDSA /etc/ipsec.d/private/ubuntu-red.key

Save and close and then type in:

ipsec restart

Setup the Host to Host VPN on ubuntu-blue

Edit the default ipsec.conf file:

nano /etc/ipsec.conf

Add the following to the bottom of the file:

conn blue-to-red
    authby=pubkey
    auto=route
    [email protected]
    leftcert=ubuntu-blue.cer
    right=192.168.145.130
    [email protected]
    type=transport
    mobike=no

Save and close that file.

Now open the ipsec.secrets file:

nano /etc/ipsec.secrets

And add the following:

: ECDSA /etc/ipsec.d/private/ubuntu-blue.key

Save and close and then:

ipsec restart

Testing

At this point you should have all the appropiate settings configurered. If on either ubuntu-red or ubuntu-blue you type in the following:

ipsec listcerts

You should have output which looks like the following, as long as it’s saying we have the private key we should be good to go.

List of X.509 End Entity Certificates:

altNames: ubuntu-red
subject: “C=US, O=IPSec VPN, CN=ubuntu-red”
issuer: “C=US, O=IPSec VPN, CN=IPSec VPN Certificate Authority”
serial: 3d:ff:cc:d0:c9:00:f9:1c
validity: not before Oct 13 19:14:16 2015, ok
not after Oct 12 19:14:16 2018, ok
pubkey: ECDSA 256 bits, has private key
keyid: f0:38:cf:e6:73:a9:af:26:45:34:03:b5:24:32:17:cd:d8:96:12:de
subjkey: d2:f5:3f:d9:e5:3d:78:4f:57:d5:c5:bd:96:84:4b:2b:b8:87:7d:54
authkey: e5:64:34:f3:00:db:7e:ea:54:eb:5e:7c:d6:e2:e2:3e:88:28:55:35

If you type in the following on ubuntu-red the tunnel should come up and give you some details.

ipsec up red-to-blue

initiating IKE_SA red-to-blue[1] to 192.168.145.131
generating IKE_SA_INIT request 0 [ SA KE No N(NATD_S_IP) N(NATD_D_IP) ]
sending packet: from 192.168.145.130[500] to 192.168.145.131[500] (1212 bytes)
received packet: from 192.168.145.131[500] to 192.168.145.130[500] (465 bytes)
parsed IKE_SA_INIT response 0 [ SA KE No N(NATD_S_IP) N(NATD_D_IP) CERTREQ N(MULT_AUTH) ]
received cert request for “C=US, O=IPSec VPN, CN=IPSec VPN Certificate Authority”
sending cert request for “C=US, O=IPSec VPN, CN=IPSec VPN Certificate Authority”
authentication of ‘ubuntu-red’ (myself) with ECDSA-256 signature successful
sending end entity cert “C=US, O=IPSec VPN, CN=ubuntu-red”
establishing CHILD_SA red-to-blue
generating IKE_AUTH request 1 [ IDi CERT N(INIT_CONTACT) CERTREQ IDr AUTH N(USE_TRANSP) SA TSi TSr N(MULT_AUTH) N(EAP_ONLY) ]
sending packet: from 192.168.145.130[500] to 192.168.145.131[500] (908 bytes)
received packet: from 192.168.145.131[500] to 192.168.145.130[500] (716 bytes)
parsed IKE_AUTH response 1 [ IDr CERT AUTH N(USE_TRANSP) SA TSi TSr N(AUTH_LFT) ]
received end entity cert “C=US, O=IPSec VPN, CN=ubuntu-blue”
using certificate “C=US, O=IPSec VPN, CN=ubuntu-blue”
using trusted ca certificate “C=US, O=IPSec VPN, CN=IPSec VPN Certificate Authority”
checking certificate status of “C=US, O=IPSec VPN, CN=ubuntu-blue”
certificate status is not available
reached self-signed root ca with a path length of 0
authentication of ‘ubuntu-blue’ with ECDSA-256 signature successful
IKE_SA red-to-blue[1] established between 192.168.145.130[ubuntu-red]…192.168.145.131[ubuntu-blue]
scheduling reauthentication in 10224s
maximum IKE_SA lifetime 10764s
connection ‘red-to-blue’ established successfully

Well done, you now have an up and running IPSec tunnel based on shared certificates!

2 Comments on "Easy(ish) IPSec VPN with Shared ECDSA Certificates for Host to Host Connections"

  1. Syed Saad Ahmed says:

    The best tutorial i have gone through uptill now, i must say that it was very easy to understand and impement !!
    will you please make a tutorial or a guide to implement ipsec based tunnel using strongswan through third party certificates or through trusted certificates provided by different providers ?
    i will reaally appreciate your help !

    • gyp says:

      Hi Syed,

      Thanks for the kind words and glad it worked for you 🙂

      For certificates from a non-shared CA you’ll need to import the certificate into “/etc/ipsec.d/cacerts” on each host.

      Then you’ll need to change the “rightid” to match the CN and –san of the other certificate.

      Next it’ll be necessary “leftid” and “leftcert” to the certificate that host is using.

      Lastly make sure your key for the certificate is in “/etc/ipsec.d/private”.

      The command “ipsec listcerts” should then display the necessary information if Stronswan can actually use those certificates.

      I’m happy to document this if needed, but it could take me a bit of time!

      Thanks for dropping by and thanks again for your kind words,

      Gyp

Got something to say? Go for it!