Configuring https on nginx

Best practices for https configuration has changed through 2013. Because of BEAST attacks on TLS, RC4 had been getting prioritised by many.

But:

  • client side mitigations to BEAST
  • strong indications that RC4 is broken
  • an increase in the use of PFS
  • (at last ) the end of Windows XP

Mean that we can prioritise some more modern ciphers.

Mozilla has produced an useful document that they recommend for their TLS web server configuration.

created some new directories beneath /etc/nginx

mkdir -p /etc/nginx/ssl/{public,private,dh}
chmod 700 /etc/nginx/ssl/private

generated a new private keys and certificate signing request

cd /etc/nginx/ssl/private
openssl req -new -newkey rsa:2048  -nodes -keyout not.burntout.org.key -out not.burntout.org.csr 
chmod 400 not.burntout.org.key # the private key needs to be private

Sent the csr off to gandi, and after domain validation recieved a x509 certificate.

This saved as not.burntout.org.pem into /etc/nginx/ssl/public, additionally the gandi intermediate certificate is required, so that is downloaded into /etc/nginx/ssl/public/gandi.pem.

These are then concatenated together.

cd /etc/nginx/ssl/public; cat not.burntout.org.pem gandi.pem > new.pem; cp new.pem not.burntout.org.pem

Generate a Diffie Hellman Prime

To make use of PFS we need a generate a Diffie Hellman Prime.

cd /etc/nginx/ssl/dh; openssl dhparam -out dh.pem 2048

Configure nginx

Add the following to you ssl server block. This is different to the Mozilla recommendations, I've removed support for SSL3

server {
  server_name         not.burntout.org;
  listen              443 ssl;
  ssl_certificate     /etc/nginx/ssl/public/not.burntout.org.pem;
  ssl_certificate_key /etc/nginx/ssl/private/not.burntout.org.key;
  ssl_protocols       TLSv1 TLSv1.1 TLSv1.2;
  ssl_dhparam /etc/nginx/ssl/dh/dh.pem;
  ssl_session_timeout 5m;
  ssl_ciphers         ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:ECDHE-RSA-RC4-SHA:ECDHE-ECDSA-RC4-SHA:AES128:AES256:RC4-SHA:HIGH:!aNULL:!eNULL:!EXPORT:!DES:!3DES:!MD5:!PSK;  
  ssl_prefer_server_ciphers on;
  ssl_session_cache shared:SSL:50m;

  # Enable this if your want HSTS (recommended, but be careful)
  add_header Strict-Transport-Security max-age=15768000;
  # ... Rest of configuration here  
  # ... 
  # ...
}