24 Dec 2014∞
I recently wrote about how best to configure one’s SSL using Nginx. Unfortunately I recommended RC4 over many other ciphers because at the time it wasn’t completely broken. That time has come to pass.
Here is my updated configuration, unfortunately dropping SSLv3 entirely (and thus blocking the default configuration for Windows XP on IE6):
ssl_certificate /path/to/combined.cert.and.ca.crt;
ssl_certificate_key /path/to/cert.key; (Make sure it's 4096-bits!)
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers "!ADH:!MD5:!aNULL:ECDH+AES:DH+AES:@STRENGTH:RSA+AES:3DES";
ssl_dhparam /path/to/strong/dhparam-4096.pem;
add_header Strict-Transport-Security "max-age=31536000";
ssl_prefer_server_ciphers on;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
ssl_stapling on;
ssl_stapling_verify on;
ssl_trusted_certificate /path/to/ca.crt;
resolver 8.8.8.8 valid=300s;
resolver_timeout 5s;
Make sure you create your strong DH parameters file (this took 45 minutes on a 2014 Mac Pro):
# openssl dhparam -out /path/to/strong/dhparam-4096.pem 4096
If you don’t care about IE on XP at all, go ahead and drop 3DES
at the end of the ssl_ciphers
list. That will give you a very strong rating on the Qualys SSL Labs Server Test tool. Also, if forward secrecy is important to you on Java 6u45, go ahead and comment out the ssl_dhparam
part.
About the only thing you can do to get a better score at this point is to really cut back on your supported clients.
- Disable TLSv1.0 and TLSv1.1 (Improves Protocol Support score) — not recommended
- Disable 128-bit cipher suites (Improves Cipher Strength score)
Here’s what that looks like:
ssl_certificate /path/to/combined.cert.and.ca.crt;
ssl_certificate_key /path/to/cert.key; (Make sure it's 4096-bits!)
ssl_protocols TLSv1.2;
ssl_ciphers "!ADH:!MD5:!aNULL:ECDH+AES256:DH+AES256:@STRENGTH:RSA+AES256";
ssl_dhparam /path/to/strong/dhparam-4096.pem;
add_header Strict-Transport-Security "max-age=31536000";
ssl_prefer_server_ciphers on;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
ssl_stapling on;
ssl_stapling_verify on;
ssl_trusted_certificate /path/to/ca.crt;
resolver 8.8.8.8 valid=300s;
resolver_timeout 5s;
As of December 24, 2014, disabling TLSv1.0 and TLSv1.1 breaks these clients (according to Qualys), so I don’t recommend it:
- Android 2.3.7
- Android 4.0.4
- Anrroid 4.1.1
- Android 4.2.2
- Android 4.3
- BingBot Dec 2013
- BigPreview Jun 2014
- Googlebot Jun 2014
- IE 6 / XP
- IE 7 / Vista
- IE 8 / XP
- IE 8-10 / Win 7
- IE Mobile 10 / Win Phone 8.0
- Java 6u45
- Java 7u25
- Java 8b132
- OpenSSL 0.9.8y
- Safari 5.1.9 / OS X 10.6.8
- Safari 6.0.4 / OS X 10.8.4
Note that this is almost entirely due to dropping TLSv1.0 and not due to the lack of AES-128. By turning back on TLSv1.0 and TLSv1.1 (lowering your Protocol Support score from 100 to 95) you only lose these clients:
- Android 2.3.7
- IE 6 / XP
- IE 8 / XP
- Java 6u45
- Java 7u25
- Java 8b132
So, to summarize, here are my current recommended configs, one to maximize client compatibility and one to maximize (practical) security.
Compatibility:
ssl_certificate /path/to/combined.cert.and.ca.crt;
ssl_certificate_key /path/to/cert.key; (Make sure it's 4096-bits!)
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers "!ADH:!MD5:!aNULL:ECDH+AES:DH+AES:@STRENGTH:RSA+AES:3DES";
ssl_dhparam /path/to/strong/dhparam-4096.pem;
add_header Strict-Transport-Security "max-age=31536000";
ssl_prefer_server_ciphers on;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
ssl_stapling on;
ssl_stapling_verify on;
ssl_trusted_certificate /path/to/ca.crt;
resolver 8.8.8.8 valid=300s;
resolver_timeout 5s;
Security:
ssl_certificate /path/to/combined.cert.and.ca.crt;
ssl_certificate_key /path/to/cert.key; (Make sure it's 4096-bits!)
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers "!ADH:!MD5:!aNULL:ECDH+AES256:DH+AES256:@STRENGTH:RSA+AES256";
ssl_dhparam /path/to/strong/dhparam-4096.pem;
add_header Strict-Transport-Security "max-age=31536000";
ssl_prefer_server_ciphers on;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
ssl_stapling on;
ssl_stapling_verify on;
ssl_trusted_certificate /path/to/ca.crt;
resolver 8.8.8.8 valid=300s;
resolver_timeout 5s;
I expect I won’t have to update this post soon — or at least not until Nginx enables support for hybrid / dual SSL certificates for the same host. (NOT SNI, but rather having an ECC and RSA certificate for the same site. Apache already supports this and Nginx developers discussed it last year.) That or when OpenSSL supports ChaCha20-Poly1305 (this is possible today by using Google’s fork of OpenSSL, BoringSSL, but it requires manually compiling all the software).