My evening started with the strange feeling something was going on with my home network. A little probing around quickly led to this semi-obvious problem:
Jul 15 23:41:32 server openvpn[6815]: 255.255.255.255:35304 VERIFY ERROR: depth=0, error=certificate has expired: /C=CA/ST=British_Columbia/L=Vancouver/O=[xxx]/CN=[xxx].ectoplasm.org
Allright, so I use OpenVPN to handle my VPN needs, and it's a fine piece of software. Does the job very well, and I feel much better using it since I've switched away from VTun. I get a much better feeling of security from something that leverages openssl that something that implements it's own cryptographic layer. Enough said.
Like every other year or so, my self-generated certificates expire and cause me a minor headache. Normally, I would just fire up TinyCA (a very nice CA GUI) and renew the certiifcates that show up as *expired*. Unfortunately, all I had handy was my MacBook Pro, and last I checked I didn't have TinyCA running on it. Bummer. The normal computer I would use for this is obviously sitting at the other end of the broken vpn connection.
Time to fall back to openssl's amusing set of command-line tools. I always get this wrong the first time around, so that's one of the self-serving reasons for blogging about it.
First, generate a new certificate signing request (CSR) from the existing key.
$> openssl req -new -key client.key -out client.csr
Then get the CA (myself) to sign the request, creating a certificate in the process
$> openssl ca -cert cacert.pem -keyfile cacert.key -out client.crt -days 365 -infiles client.csr
This now gives us a brand new client certificate good for another year (365 days). Of course, to make things a bit more entertaining, my particular OpenVPN configuration requires PKCS12 key/certificates, so I need to generate that too:
$> openssl pkcs12 -export -certfile cacert.pem -in client.crt -inkey client.key -out client.p12
That was almost easy. Copy the new client.p12 file on top of the old one and restart OpenVPN. Job done!
Jul 16 00:37:37 server openvpn[6815]: 255.255.255.255:33826 VERIFY ERROR: depth=0, error=unsupported certificate purpose: /C=CA/ST=British_Columbia/O=[xxx]/CN=[xxx]
Wait a sec, unsupported certificate purpose ? That's a new one, and hopefully, this might be really helpful to somebody else with a problem similar to mine. This is part of the certificate verification process. There are client certs and there are server certs. OpenVPN clients verify that the certificate of the server they are talking is a server certificate, and servers make sure clients are using client certificates. As it turns out, my manually generated certificates ended up being server certs, not client certificates.
I will skip over the frustrating process of figuring out how to make openssl generate client certs instead of server certs, but the final solution is, as would have been expected, just one more command-line switch to openssl. When signing the CSR and generating the certs, use this openssl invocation instead:
$> openssl ca -extensions client_cert -cert cacert.pem -keyfile cacert.key -out client.crt -days 365 -infiles client.csr
There you have it, -extensions client_cert. I don't know if my Googling skils are weak, but it took me a bit longer than I expected to finally figure this one out.
See you in another year!