Different SSL protocols for different server blocks on the same port

Maxim Dounin mdounin at mdounin.ru
Tue Apr 28 14:24:30 UTC 2015


On Tue, Apr 28, 2015 at 02:00:07PM +0000, Aviram Cohen wrote:

> Hello!
> The Nginx configuration allows you to define different server 
> blocks that have different server names but listen on the same 
> port in SSL. For an incoming connection, Nginx uses SNI in order 
> to know under which server block the connection should be 
> handled.
> However, the 'ssl_protocols' directive doesn't work as expected 
> in this scenario.
> Let's say that we have two servers blocks - the first allows 
> TLSv1, TLSv1.1 and TLSv1.2, and the second allows only TLSv1 
> connections ('ssl_protocols TLSv1;' directive). From what I've 
> seen, in this case, the second server will still accept incoming 
> TLSv1.1 and TLSv1.2 connections.
> I've debugged it a bit, and wrote some independent code that 
> uses OpenSSL, and it seems that OpenSSL doesn't allow you to 
> change the supported TLS versions of a connection during the SNI 
> callback.
> The following may occur - an incoming connection to the second 
> server starts, and it gets the default SSL CTX object (in Nginx, 
> that would be the context of the first server block). When the 
> SNI callback (ngx_http_ssl_servername) is called, the context is 
> replaced for the connection (with the context of the second 
> server block), along with the SSL options of the connections 
> (SSL_set_options is called with the new CTX's options). These 
> options contain the second server's allowed protocols. Even 
> though the correct options are set, when the handshake 
> continues, it would succeed even for TLSv1.1 and TLSv1.2 (which 
> are enabled for the first server, but not for the second one).
> A similar problem can occur as well; for example, if the first 
> server allows only for TLSv1 connections and the second one 
> allows for TLSv1.1, then TLSv1.1 connections will be rejected by 
> OpenSSL, even if their SNI name is the name of the second 
> server.
> This seems like an OpenSSL issue (I've reproduced it on both 
> v1.0.1 and v1.0.2), but I think that this should at least be 
> documented in Nginx's SSL documentation, as the 'ssl_protocols' 
> directive doesn't behave as expected for different server blocks 
> with the same port - you'd  expect that one server block would 
> not affect the other, but it does.
> Nginx development team (e.g. Maxim, Igor), I'd love to hear your 
> thoughts about this.
> Below is an example of this scenario.

This was discussed a while ago, see here and previous messages:


In short: there are some cases which should work IMHO, but don't 
due to OpenSSL behaviour.  There are other cases which aren't 
expected to work at all, even theorethically.

I don't think that OpenSSL behaviour here is a bug - the SNI 
callback can only happen once OpenSSL started processing of a 
ClientHello message, and it basically means that it already chosen 
a protocol to use.  While in theory it can be possible to choose 
another protocol - it will seriously complicate things.

I also think that people trying to do such things with SNI 
are utterly wrong.  

Maxim Dounin

More information about the nginx-devel mailing list