Update: current Nginx (1.10.1) and OpenSSL (1.0.2h) have good defaults. None of this is needed anymore \o/
In a search to ensure forward secrecy on all servers I manage, I needed to figure out a list of ciphers I want to use. There are numerous articles on the web that tells you what to use, but they are either vague about what really to use, or give you a long list of things you don’t know or care about. After quite some reading and experimenting I finally got a grasp of it, and the end result is not as scary as what those articles say.
There is also a tldr at the end for the lazy ;)
Forward Secrecy and Cipher Suites
Forward secrecy means that in the event of a breach, a key stolen from either side cannot be used to decrypt conversations that happened in the past.
A cipher suite is a combination of a key exchange algorithm, an authentication algorithm, an encryption algorithm and a MAC (message authentication code) algorithm.
In order to achieve forward secrecy, the connection needs to be protected by a cipher suite that uses the DH key exchange algorithm, or its faster (but no less secure) variant ECDH.
Meet OpenSSL
man openssl
does not tell you how to list all the cipher suites using DH and
ECDH. The documentation about ciphers does, to some extent, but for some
reason DH is sometimes called DHE and EDH, while ECDH is called ECDHE and ECDH
interchangeably. Ironically I didn’t even know that I was looking for DH and
ECDH. The blog posts I found imply that I can search using the command openssl
ciphers -v <cipher_string>
.
[sarcasm] Neat, now I just need to find out what my cipher string is… [\sarcasm]
After spending some time searching around I found the magic word: openssl
ciphers -v DH
. This shows all cipher suites using DH.
Building the Best Cipher String
A list of cipher suites using DH and ECDH can be retrieved with openssl
ciphers -v 'ECDH DH'
. Note that I deliberately put ECDH first, because it is
faster.
That’s not it yet, because the list contains cipher suites that don’t have
authentication. You want to exclude those: openssl ciphers -v 'ECDH DH
!aNULL'
It also contains suites that use weak encryption algorithms. Fortunately and
conveniently there is a group containing suites using strong encryption
algorithm. You need to and
it with your list: openssl ciphers -v 'HIGH+ECDH
HIGH+DH !aNULL'
Finally, add other suites (that don’t support forward secrecy) so that you can cater for old sucker clients:
openssl ciphers -v 'HIGH+ECDH HIGH+DH HIGH !aNULL'
TLDR
Use this in Nginx:
ssl_ciphers 'HIGH+ECDH HIGH+DH HIGH !aNULL';
This post is written with the help of:
- Qualys SSL Labs Server Test: If you haven’t analyze your site with this tool, do it now. Thank me later.
- Security/Server Side TLS - MozillaWiki: The article has a lot of details regarding SSL and TLS, including how to configure Apache, Nginx and other servers.
Questions or comments can go to Hacker News :)