UPDATED 2016-02-12 - Yes, I know it’s TLS, but the acronym SSL is still so widely-used to refer to both SSL and TLS, it makes sense to leave the title as-is. CHANGES: Simplified configuration by removing
listen lines and server block, since it’s best to make the SSL options global anyway. You can choose which sites to add the headers to, but any using SSL/TLS should probably have them. Also removed lots of text below. Thanks to cipherli.st for some extra config options I was missing, but I still only need 4 ciphers to cover the majority of browsers, so I’ll keep updating mine in the mean time.
Have you seen the recent (and not so recent) OpenSSL/TLS protocol vulnerabilities, and are you worried about securing your clients’ connections to the Nginx servers for which you are responsible?
I’m going to assume you answered “yes” to that question, as it’s unlikely you’d end up on this page otherwise. The whole purpose of this post is to share some high-security SSL configuration info for Nginx, so you’ve come to the right place.
DISCLAIMER: YOU SHOULD NOT TRUST ME OR BLINDLY COPY AND PASTE MY CONFIGURATION INTO YOUR NGINX CONFIGURATION FILE WITHOUT UNDERSTANDING WHAT EACH OPTION DOES AND WHY EACH CONFIGURATION VALUE WAS CHOSEN. CONSIDER YOURSELF AND ANY ANIMALS HARMED BY USING MY CONFIGURATION SUFFICIENTLY WARNED
Here is an example configuration template that should support most browsers currently in use today, while preferring very high levels of security on modern browsers, and effectively mitigating most older/newer attacks:
## HTTPS globals ssl_protocols TLSv1 TLSv1.1 TLSv1.2; ssl_ciphers ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES256-SHA; ssl_prefer_server_ciphers on; ssl_dhparam /path/to/dh4096.pem; # >2048-bits recommended ssl_session_cache shared:SSL:10m; ssl_session_timeout 10m; ssl_session_tickets off; # Requires nginx >= 1.5.9 ssl_ecdh_curve secp384r1; # Requires nginx >= 1.1.0 resolver 18.104.22.168 22.214.171.124 valid=300s; resolver_timeout 5s; ssl_stapling on; # Requires nginx >= 1.3.7 ssl_stapling_verify on; # Requires nginx >= 1.3.7 ## Headers to add inside server blocks add_header Strict-Transport-Security "max-age=31536000"; # Add "; includeSubdomains" if all accessible subdomains are also secured with TLS (SSL) add_header X-Frame-Options DENY; add_header X-Content-Type-Options nosniff;
As you can verify by checking shellvatore.us on the SSL Labs test site, these configuration options, combined with the latest stable versions of OpenSSL and Nginx, score an A+ while still allowing all browsers that support TLS1.0 and up (and ECDH) to connect.
Some of the above options will not work in older versions of Nginx, and they’ve been marked with comments to give an idea of which versions are capable of using them.
Please feel free to send me any comments you may have on possible improvements to the configuration above.