Securing your site with nginx

Posted in Privacy Security with tags cryptography howto HSTS nginx PFS -

This week in the Netherlands the news hit again that some secure websites where vulnerable to a downgrade attack. This attack is not new, but for the average user it is hard to detect. You have to be careful that you see the lock when you are entering your credentials.

Fortunately, most new web servers and browsers have a setting for it, called HTTPs Strict Transport Security (HSTS). With that feature enabled, if your browser has ever contacted a website over a secure link (HTTPS), then it will not allow a downgrade to plain HTTP for that host. This of course means that you are more secure, at least as long as you watch out for certificate warnings. I use the nginx webserver, and use some other things for security, which I’ll share with you below. The SSLLabs test will give this configuration an _A+ _currently.

Edit 26/3: @okoeroo gave me a better list of ciphers which scores even higher with SSLabs:

The nginx webserver is a delight to configure. I’ve been using Apache for a long time, but moved over to nginx some time ago. I had planned a couple of days to switch, but I was done in an afternoon. nginx configuration files are simple, brief and easy to understand. I’m going through the configuration of this site here piece by piece, the complete configuration file is included at the end for your copy-paste enjoyment.

The first part defines a server object that listens on IPv4 and IPv6 port 80, using the name It then uses a 301 (Moved Permanently) code to redirect the browser to the https variant. Note that this in itself is not HSTS yet, but comes close.

Basic stuff so far to setup an SSL server listening on IPv4 and IPv6 port 443.

This is where the important stuff happens. We add the SSL certificate and it’s key. For nginx the certificate should contain the complete chain to the trust anchor.

We also add an Ephemeral Diffie-Hellman parameters file to make sure that we use a 2048 bit key-exchange (otherwise the 2048 bit certificate would be kind of pointless). You generate this file using the ‘openssl dhparam -out dhparam.pem 2048‘ command. (Source).

The next line adds the Strict Transport Security header, with a max-age of about six months (taken from the RFC). Note the quoted “max-age=…” value, many nginx tutorials forget these and then it does not actually work.

Finally we get to the SSL ciphers. I have set the server to dictate the choice of ciphers, which is then defined in the next line. The ciphers at the end with “!” in front of them are explicitly disabled. The other ciphers are in order of preference. This list deliberately starts with ephemeral elliptic curve ciphers, and AES. These implement Perfect Forward Secrecy, which protects you from future key compromises. Another reason is because we should be moving away from RSA. This setting does mean that IE on XP will not be able to reach your site, but they have other problems to deal with anyway.

OCSP is a protocol to check for certificate revocations. Browsers can do this, but it presents a privacy threat, and also adds overhead. However, the webserver can also do this itself. It regularly contacts the CA to get a signed response that the certificate is still valid, and then ‘staple’ this onto the handshake. To make sure that the CA is also not tampered with, the staple response is also verified using the trusted chain to that CA (the other certs you include in the certificate above).

The final part of the configuration defines the root of the site (note the trailing “/”). It defines the order in which index files are attempted, and the location of the log files for this server.
There’s a setting to be able to upload files, and a fastcgi buffer setting.

Then I continue with a rewrite rule for files that aren’t found so that WordPress can pick those up. WordPress itself is in PHP, so we need the fastcgi_pass to pass it on to a php_fpm daemon, with the appropriate settings. And then we close off with a caching setting for images, css, javascript and swf files that I copied from (an older version) of the nginx wiki on WordPress.

Written by