Thoughts on technology and mathematics

Secure Your Services Using Sane Cipher Ordering

For a while I’ve been enforcing encrypted connections for my servers wherever possible. However, I trusted the client software to make somewhat smart decisions about what ciphers they use. This is - as it turns out - at least currently not a good idea.

OpenSSL especially seems to have had a very weird default ordering for ciphers in older versions and a lot of software depends on this library, so often you end up using RC4 (a cipher whose biases have been known for a decade and whose use is discouraged) without ephemeral key exchange when both client and server could do a lot better.

One example for this is my mobile mail client, K9 Mail (using both the most current client and OS version available, K9 Mail 4.801, Android 4.4 KitKat): With the default postfix configuration it uses 128bit RC4-MD5 for sending mail, which is a terrible choice.

What cipher ordering is all about

In an SSL/TLS handshake both the client and the server will have a list of cipher suites they are willing to use. Normally, the server selects the first cipher from the client’s list it finds acceptable.

If you make an informed choice about which cipher suites you prefer however, it is probably more appropriate to use the first cipher from your list that the client also supports. This allows you to support weaker ciphers for broken client if needed, but use the best available cipher for everyone else.

Getting a cipher list you are comfortable with

You can find out about the ciphers your OpenSSL library supports by typing openssl ciphers -v ALL on the terminal. This will return a list like this:

ECDHE-RSA-AES256-SHA384       TLSv1.2 Kx=ECDH Au=RSA   Enc=AES(256)    Mac=SHA384

For each cipher suite this will tell you:

  • Which SSL/TLS version it applies to
  • the key exchange algorithm used
  • the authentication algorithm used
  • the encryption algorithm used and
  • the mac algorithms used.

Instead of ALL you can use any string that is valid as a cipher order spec in OpenSSL. This includes special classes of suites that are grouped together by the library itself, such as HIGH or EXPORT (for a full list, see man 1 ciphers). You should prefer using those classes over specifying the ciphers individually unless you are prepared to update your list whenever the library is updated to reflect the current state-of-the-art in cryptography research.

A good idea is to look at the default of the server software you are using and then add or remove (classes of) cipher suites until you’re comfortable with the resulting output of openssl ciphers. Always explicitly forbid anonymous cipher suites (ones that don’t use certificates and are therefore susceptible to man-in-the-middle attacks) using !aNULL and consider adding @STRENGTH at the end of your list, which will ask OpenSSL to sort the ciphers by key length.

Using your cipher order with server software


To use the server’s cipher preference order, set tls_preempt_cipherlist = yes.

Postfix has five internal lists of ciphers that the authors suggest should not be changed. Which of the lists is used, is determined by the configuration settings smtpd_tls_ciphers and smtpd_tls_mandatory_ciphers. The latter applies only when the encryption was mandatory for this connection, whereas the former will be used for opportunistic encryption. You have a choice between (from most to least secure) high, medium, low, export and null. Check the output of postconf -d for the parameters tls_high_cipherlist, tls_medium_cipherlist and so on to see which ciphers are in which list.

The default configuration uses medium, which allows RC4 among others, for mandatory encrypted connections and export, which includes ciphers that can only be considered scrambling such as 40bit DES. I decided to require strong ciphers for mandatory encryption and reasonable ciphers for everything else, so I ended up with the following:

tls_preempt_cipherlist      = yes
smtpd_tls_mandatory_ciphers = high
smtpd_tls_ciphers           = medium

smtp_tls_mandatory_ciphers  = $smtpd_tls_mandatory_ciphers
smtp_tls_ciphers            = $smtpd_tls_ciphers
lmtp_tls_mandatory_ciphers  = $smtpd_tls_mandatory_ciphers
lmtp_tls_ciphers            = $smtpd_tls_ciphers


Using the server’s cipher preference is a really recent addition to Dovecot. You will need at least version 2.2.6 (released on 2013-09-25) to use the option: ssl_prefer_server_ciphers = yes.

Using a restrictive list of ciphers is probably a good idea until this version has landed in your distribution. The default again allows the ciphers from the MEDIUM suite, including RC4. Unless one of your users insists on using ancient mail clients, this should be a good setting:

ssl_cipher_list = HIGH:!SSLv2:!aNULL@STRENGTH
# only enable on dovecot 2.2.6 and later:
#ssl_prefer_server_ciphers = yes


To force server preference, use SSLHonorCipherOrder on, the list of allowed ciphers is specified using SSLCipherSuite. Both settings can be found on Debian systems in /etc/apache2/mods-enabled/ssl.conf.

A possible configuration would look like this:

SSLHonorCipherOrder on

Please note that even though openssl ciphers may list ciphers using elliptic curve key exchange (ECDHE_*) these cannot be used with any Apache version prior to Apache 2.4. Also, even though RC4 is considered insecure and even Microsoft says you should disable it there might still be a small number of users who depend on it. If you want your website to be as compatible as possible, include the MEDIUM class ciphers in your list.


For prosody, you have to edit the ssl section of your configuration file. The server side ordering of ciphers is hidden in the options key. Note, that you have to include the defaults ("no_sslv2", "no_ticket", "no_compression" as of 0.9.1) or you will implicitly disable them.

A modified configuration could then include:

ssl = {
    options = { "no_sslv2", "no_ticket", "no_compression", "cipher_server_preference" };
    ciphers = "HIGH:!SSLv2:!aNULL@STRENGTH";

Update, 10.01.2014: Since version 0.9.2, prosody uses the server’s cipher preference and disables RC4 by default. So if you have prosody 0.9.2 or newer, please remove the custom ssl options and ciphers from your configuration. Hopefully, other software vendors will follow this example soon.