The perfect SSL NGINX configuration

NGINX

Last Updated: 11/16/2016

At Commando.io we make sure we are always on top of any potential security exploits or vulnerabilities. Unfortunately, lately there has been a steady stream of SSL related issues (Heartbleed and POODLE come to mind). Fortunately patching some of the most prominent issues only requires updating a few NGINX directives.

We figured we would share our SSL NGINX configuration blocks which are used on all Commando.io web servers. Let's break the NGINX directives into two logical sections. The first being security and the second related to performance and optimization.

Security
http {  
    ssl_prefer_server_ciphers on;
    ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
    ssl_ciphers 'ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES256-SHA:ECDHE-ECDSA-DES-CBC3-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:DES-CBC3-SHA:!DSS';
}

The above configuration provides robust perfect forward secrecy and mitigates against POODLE by removing SSLv3 support. It should also result in an A rating on Qualys SSL LABS as well. If you'd like an A+ rating, you'll need to implement strict transport security as well.

See the Commando.io SSL LABS report at: https://www.ssllabs.com/ssltest/analyze.html?d=commando.io

Note: This cipher suite does prevent some older clients (specifically IE6 on Windows XP) from establishing connections, but the majority of our traffic comes from users on Chrome so this is a non-factor for us. Evaluate your requirements by looking at your own traffic.

Performance
http {  
    ssl_stapling on;
    ssl_stapling_verify on;
    ssl_trusted_certificate /etc/nginx/ssl/stapling.trusted.crt;  
    resolver 8.8.4.4 8.8.8.8 valid=300s;
    resolver_timeout 10s;

    ssl_session_cache shared:SSL:32m;
    ssl_buffer_size 8k;
    ssl_session_timeout 60m;
    ssl_session_tickets off;
}

server {  
    # you may replace spdy with http2 if your version of NGINX supports HTTP/2
    listen 443 deferred ssl spdy;
}

The first set of performance directives enables OCSP stapling. We've written a dedicated blog post on OCSP stapling previously, so check that out for more information.

Next, we enable NGINX SSL cache, which provides SSL session resumption support. We allocate a shared 32MB of space (one megabyte can store about 4000 sessions according to the NGINX documentation). We set a 60 minute timeout on SSL sessions and also set ssl_buffer_size to 8K to minimize time to first byte (the NGINX default is 16K).

Finally, in the server block we enable the deferred directive and turn on SPDY support. You may replace spdy with http2 if your version of NGINX supports HTTP/2. Verify that SPDY is enabled on your site with SPDYCheck a great service by zoompf.

We'd also like to recommend a great service we recently found and signed up for called Snitch. Snitch will automatically check your SSL certificate and configuration at specified intervals. It looks for upcoming expiration, security issues, and performance recommendations and then alerts you of anything that needs attention.