One ssl_protocols to rule them all

For some time now, I’ve hoped to disable support for TLSv1 and TLSv1.1, and move to Mozilla’s “modern” cipher suite. Unfortunately, due to one application not supporting this combination of protocols and ciphers, I’ve been unable to make the switch.

I recently refreshed my ciphers as taken from the Mozilla documentation, and in doing so, found myself reviewing the nginx reference for its ssl_ciphers and ssl_protocols directives. A bit to my surprise, and seeming too good to be true, the documentation notes that both directives are supported in the http and server contexts, which appeared to solve my problem–all but the offending application would drop support for anything other than TLSv1.2. Sadly, my excitement was short-lived. As I quickly learned, and as has been discussed several times before, all but the first ssl_protocols directive are ignored.

The issue actually lies with OpenSSL, not nginx, and how the former handles connections using SNI, or Server Name Identification. SNI allows one IP address to serve multiple domains securely, whereas previously, dedicated IP addresses were required per SSL certificate. When OpenSSL negotiates a secure connection, it checks the allowed protocols once–before SNI is completed–which means only the default protocols are respected. Since OpenSSL doesn’t re-negotiate supported protocols after SNI, my hope of supporting TLSv1 for just one server block was dashed (perhaps).

From the nginx mailing list, November 2014:

In theory, this depends on the OpenSSL library behaviour and may work as long as SNI is used – nginx does it’s best to update all SSL options on SNI callback.

With current OpenSSL code it doesn’t seem to work though, as protocols allowed are checked before SNI callback happens and not rechecked afterwards. So yes, you are right – “ssl_protocols” won’t do anything good in non-default server{} blocks, even if SNI is used.

Maxim Dounin

Even after writing this, supporting TLSv1 and TLSv1.1 still bothers me enough that I’m likely to devise some other solution to this problem. More to come… 😀