TLS Update: OCSP and HSTS

What SSL/TLS needs is more acronyms! I bring you OCSP and HSTS - my ongoing efforts to improve TLS security on the servers I manage ... This is a follow-up to SSL Doesn't Really Exist - How to Set Up TLS, which you should probably read first if you're foolishly following my instructions about TLS.

Online Certificate Status Protocol

OCSP is - in theory, anyway - a solution to the problem of Certificate Revocation. When a client web browser visits a secure website, it should always check if the certificate that the website sent is still valid - has the certificate been revoked? But to do this, the client has to make a separate call to the Certificate Authority to check for revocation. This created at least three new problems:

  1. the client is now burdened with making two calls instead of one: one to get the webpage and certificate, and another to a certificate authority.
  2. popular sites can cause a strain on certificate authorities as thousands of clients per second request the revocation information for the site
  3. a privacy issue is created for the client - making a query to the C.A. tells the C.A. what sites you're visiting

OCSP Stapling mostly takes care of these problems. The website talks to the C.A. at regular intervals to retrieve signed proof (signed by the C.A.) that the site certificate is still valid, and it attaches this to the certificate. It seems to me that this makes so much sense it ought to be automatic, but it's not, so let's activate it in Nginx. See the Digital Oceans link in the Bibliography for Apache instructions.

Knowing that, it turns out to be easy to enable for Nginx:

ssl_stapling on;
ssl_stapling_verify on;
ssl_trusted_certificate /path/to/root_CA_cert_plus_intermediates.pem;

If your certificate includes both your own certificate and your certificate authority's cross-signing certificate (which is probably the best plan anyway) "ssl_trusted_certificate" should simply point to your main certificate (same as "ssl_certificate"). I haven't tried any other method, although I suspect if you don't have the intermediate cert combined with your own, this could point to a stored copy of the intermediate?

Digital Ocean (link in the Bibliography) points out a very nice test:

echo QUIT | openssl s_client -connect <FQDN>:443 -status 2> /dev/null | grep -A 17 'OCSP response:' | grep -B 17 'Next Update'

Replace <FQDN> with the hostname you're interested in. To find out more about openssl s_client, use man s_client - although openssl's classically inconsistent documentation means that if you want to know what -status means, you'll have to run openssl s_client --help ("-status - request certificate status from server"). The two grep commands just chop the output down to the "OCSP response" section - although its reliance on that section always being 17 lines is NOT future-proof (these things change all the damn time).

HTTP Strict Transport Security

Another place you can make things more secure is HSTS - basically, you set your server up to say "never talk to me any way but securely." This prevents a number of downgrade/MITM attacks that hijack a web connection and reduce the security involved: see Wikipedia's entry on the subject for a more complete explanation. Again, the Nginx setup is quite simple:

# HSTS (ngx_http_headers_module is required) (15768000 seconds = 6 months)
add_header Strict-Transport-Security max-age=15768000;

Mozilla's "SSL" Discussion and Configuration Generator

You should also check out https://wiki.mozilla.org/Security/Server_Side_TLS - this has recommendations and allows generating config files for Nginx and Apache, for a variety of scenarios. I'm likely to use it myself, if only for the ssl_ciphers - which I'm willing to believe they understand better than I do.