SSL configuration on nginx

This SSL configuration for nginx achieves an A on the SSL labs tool. It’s what this server currently uses.

We disable older, insecure versions of SSL, allowing only TLSv1 and newer:

ssl_protocols TLSv1 TLSv1.1 TLSv1.2;

(Previously, I included SSLv3, but it looks like that’s no longer required.)

For a bit of a performance boost, we can cache SSL sessions:

ssl_session_cache shared:SSL:5m;
ssl_session_timeout 10m;

This is potentially problematic, because session resumption data could be compromised. Adam Langley gives a good overview of this.

Perhaps the most important part is this cipher suite. It brings ciphers that offer forward security, and which are resistant to the BEAST attack, to the top. SSL compression is already disabled by default to block the CRIME attack, so there is nothing in the server configuration for that.

ssl_prefer_server_ciphers on;

That cipher suite string is cobbled together based on advice from Remy Van Elst, Jacob Appelbaum’s duraconf project, trying to copy what Google does, and probably other sources. (Which suggests that it is much too difficult to configure an appropriate cipher suite)

We also want to make it easy for clients to verify our certificate’s validity with OCSP. We can set the resolver to enable that, but we can also send a signed OSCP response ourselves, to save the client an extra network round-trip.

ssl_stapling on;
resolver ...;
ssl_stapling_verify on;
ssl_stapling_file ssl/ocsp.der;

Finally, to encourage the use of SSL, I’ve added the Strict-Transport-Security header. HSTS aims to mitigate SSL stripping attacks (first demonstrated by Moxie Marlinspike). The HSTS header tells clients which support this standard to only connect to the site over HTTPS for the next little while. (max-age is given in seconds; 31536000 seconds == 12 months, and the countdown is restarted every time the client sees the header, so “the next little while” can effectively be forever.) This server configuration allows clients to connect with HTTPS or HTTP. If you don’t use encryption, you’ll still be sent this header. However, clients ignore it unless it was received via HTTPS. So, in this configuration, once you connect over SSL, your client should stick to SSL.

add_header Strict-Transport-Security "max-age=31536000";