How to make OCSP stapling on nginx work

Its a bit tricky to get OCSP stapling on nginx right. But with a little effort it is possible to reap the privacy, security and performance benefits.

Setup

Mozilla recently published a security web server configurator, that makes it easy to get started. Based on this configuration, we’ll just insert the blanks.

All examples assume that you use a COMODO PositiveSSL certificate, although the procedure should be almost identical with other certificate providers. I simply stuck with it, because Comodo offers the probably most inexpensive SSL certificates out there, that support SHA256 and do not have to be renewed every year.

Ensure the correct certificate chain

You should have received these four files from Comodo after finishing the verification process:

I initially made the mistake to include the AddTrustExternalCARoot.crt file in the certificate chain. Doing so resulted in a “Contains Anchor”-warning at SSLLabs SSL-Test.

Instead, completely ignore this file, and use the following order when concatenating the files needed for creating the server SSL-certificate file in nginx:

$ cat your_server.crt COMODORSADomainValidationSecureServerCA.crt COMODORSAAddTrustCA.crt > /path/to/signed_cert_plus_intermediates

Next we need a file containing trusted CA certificates for verifying OCSP responses:

$ cat COMODORSADomainValidationSecureServerCA.crt COMODORSAAddTrustCA.crt > /path/to/root_CA_cert_plus_intermediates

As you can see, the chain has the same order, but does not contain the server certificate itself. If you are in hurry, and just need the Comodo CA-trust file, check out this OCSP stapling on nginx gist.

Priming the OCSP response cache

You might be confused as to why OCSP stapling still isn’t working right away.

This is, because nginx will not prefetch OCSP responses at server startup (or after reload), but instead, the first incoming request will be used to trigger a OCSP verification request.

There are two possible solutions to priming the OCSP cache in nginx: Either immediately perform a lookup and hope yours to be the first request to the web server, or perform a OCSP request and save the response to a file (before starting nginx). Then you can use the ssl_stapling_file directive to point nginx to the file’s location.

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

If you execute the command above, and receive a valid OCSP response, you will notice that the last line in the output contains a field called “Next Update”. It is advisable to query the certificate authority’s OCSP responder in a timely manner at this time. Otherwise there is chance OCSP stapling isn’t working (again); at least until the next response has come in.

A fast and reliable IP-address resolver can help reduce the time it takes for a verification response to come in:

server {
  # ... other settings ...

  resolver 8.8.8.8 valid=360s ipv6=off; # Google DNS
}

Update 2016-03-05

A too short resolver timeout can be another reason for OCSP stapling to fail (temporarily). If the nginx resolver_timeout directive is set to very low levels (< 5 seconds), log messages like this can appear:

2016/02/20 16:09:00 [warn] 1682#1682: "ssl_stapling" ignored, host not found in OCSP responder "ocsp.comodoca.com"

It may help to increase the resolver timeout to something around 10 seconds, or resetting it to the default of 30 seconds.

Summary

It would be nice if there was a built-in way of pre-fetching OCSP responses in nginx. At the same time I understand the architectural decision that is behind the current implementation.