Friday 4 November 2016

Cisco VPN with OpenSSL Certificates

Having realised the impracticality of a DMVPN with 10+ spokes (and dynamic spoke-to-spoke shortcut tunnels) using pre-shared keys for authentication, I decided to look into using certificates. This is something I had never done, and it appears this can be pretty straightforward, especially using the Cisco IOS CA server.

However... for whatever reason, I decided I wanted to use OpenSSL to do all my certificate issuing. So here is how I did it.

The basis of the way it works is simple: every router has a certificate, which it uses to authenticate to every other router and you don't need a pre-shared key for each router-to-router tunnel. This is all validated by having all the certificates issued by a single central Certification Authority. So, if Router A and Router B try to establish a VPN and both sides have a certificate signed by the same CA, they can use the keys associated with these certificates to establish the tunnel. *Much* easier than a lot of PSKs.

I'll illustrate this with a basic VPN setup, rather than DMVPN. I'll assume that you already understand basic site-to-site IPSEC tunnels, but here's roughly the configuration I used. Two routers with 10.0.0.0/30 for WAN addressing, and I'll use 192.168.0.0/30 for the tunnel addressing:

crypto isakmp policy 10
 encr 3des
 hash md5
 group 2

 authentication rsa-sig
 lifetime 28800


crypto isakmp identity hostname


crypto ipsec transform-set Basic esp-3des esp-md5-hmac
 mode transport


crypto ipsec profile SecTunnel
 set transform-set Basic
 

interface Tunnel0
 ip address 192.168.0.1 255.255.255.252
 tunnel source FastEthernet0/0
 tunnel destination 10.0.0.2
 tunnel protection ipsec profile SecTunnel

interface FastEthernet0/0
 ip address 10.0.0.1 255.255.255.252


This is pretty straightforward, although note the use of "authentication rsa-sig" in the ISAKMP policy! You also have to make absolutely sure your clocks are synchronised. I recommend running NTP. This is something often overlooked in a basic Cisco lab.

So, now we need to generate a CA certificate. Unlike for web servers and the like, you don't need to generate a CA and then an Intermediate certificate - you just generate a single certificate that will then sign all router certificates.

openssl req -x509 -newkey rsa:4096 -keyout vpnca.key -days 365 -out vpnca.crt

Enter a password when prompted, you'll need it later. Also fill in basic details. In this instance they don't matter too much.

$ openssl req -x509 -newkey rsa:4096 -keyout vpnca.key -days 365 -out vpnca.crt
Generating a 4096 bit RSA private key
...................................++
writing new private key to 'vpnca.key'
Enter PEM pass phrase:
Verifying - Enter PEM pass phrase:
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:GB
State or Province Name (full name) [Some-State]:London
Locality Name (eg, city) []:
Organization Name (eg, company) [Internet Widgits Pty Ltd]:Useful Company Ltd
Organizational Unit Name (eg, section) []:
Common Name (e.g. server FQDN or YOUR name) []:testca.mydomain.com
Email Address []:

This will create your key (vpnca.key) and your certificate (vpnca.crt).

Now you should create your keys on the router:

ip domain-name <your domain>
crypto key generate rsa modulus 2048 general-keys

MyRouter(config)#crypto key generate rsa modulus 1024 general-keys
The name for the keys will be: MyRouter.mydomain.com

% The key modulus size is 1024 bits
% Generating 1024 bit RSA keys, keys will be non-exportable...[OK]

This has created the keys we need. Next you need to create and authenticate your CA Trustpoint on the router:

Create:
MyRouter(config)#crypto ca trustpoint CARoot
MyRouter(ca-trustpoint)#enrollment terminal
MyRouter(ca-trustpoint)#revocation-check none

Authenticate. Paste the contents of vpnca.crt in when prompted, minus the header and footer:

MyRouter(config)#crypto ca authenticate CARoot

Enter the base 64 encoded CA certificate.
End with a blank line or the word "quit" on a line by itself

MIIFhTCCA22gAwIBAgIJAKdOkXFRpOkLMA0GCSqGSIb3DQEBCwUAMFkxCzAJBgNV

--- snip ---
RmApUW1+BZYoab6VsgRrabfPx5e5Gxp7EA==

Certificate has the following attributes:
       Fingerprint MD5: 1B63EEB6 2B9A75C1 1115BF2C 5630C5A9
      Fingerprint SHA1: 3D90F95A 89B608B2 695A2FAD CECD5857 6BD02636

% Do you accept this certificate? [yes/no]: yes
Trustpoint CA certificate accepted.
% Certificate successfully imported


This will set up your trustpoint. Now you should generate a Certificate Signing Request:

MyRouter(config)#crypto ca enroll CARoot
% Start certificate enrollment ..

% The subject name in the certificate will include: MyRouter.mydomain.com
% Include the router serial number in the subject name? [yes/no]: no
% Include an IP address in the subject name? [no]: no
Display Certificate Request to terminal? [yes/no]: yes
Certificate Request follows:

MIIBhjCB8AIBADAmMSQwIgYJKoZIhvcNAQkCFhVNeVJvdXRlci5teWRvbWFpbi5j
---snip---

NMVFrfGZM5zIDg==

---End - This line not part of the certificate request---

Copy the Base64-encoded CSR into your clipboard and then paste into a file on your server for SSL, call it "<hostname>.csr". Make sure it has the appropriate PEM header/footer:
-----BEGIN CERTIFICATE REQUEST-----
MIIBhjCB8AIBADAmMSQwIgYJKoZIhvcNAQkCFhVNeVJvdXRlci5teWRvbWFpbi5j
---snip---

NMVFrfGZM5zIDg==
-----END CERTIFICATE REQUEST-----

Now we sign the certificate - enter the CA key password from earlier when prompted:

$ openssl x509 -req -days 365 -CA vpnca.crt -CAkey vpnca.key -CAcreateserial -in MyRouter.csr -out MyRouter.crt
Signature ok
subject=/unstructuredName=MyRouter.mydomain.com
Getting CA Private Key
Enter pass phrase for vpnca.key:


Now we look inside the MyRouter.crt file produced and copy the Base64 portion of the certificate. Then we can go back to our router and import it:

MyRouter(config)#crypto ca import CARoot certificate

Enter the base 64 encoded certificate.
End with a blank line or the word "quit" on a line by itself

MIIDdzCCAV8CCQD37zWqJTK0NjANBgkqhkiG9w0BAQsFADBZMQswCQYDVQQGEwJH
---snip---
heaHO96lAMJ6QnjUMtcVpi0UwEHTeCPWC/96

% Router Certificate successfully imported



Your certificate is now imported!

If you now repeat this exact same process on your other router, your VPN should be ready. It may not come straight up, you may need to clear SAs to have it reinitialise. Congratulations, you are now using RSA Signature Authentication instead of Pre-Shared Key!