Opened 15 months ago
Last modified 14 months ago
#2542 new defect
ssl_ecdh_curve is sometimes ignored in server blocks
Reported by: | Avamander | Owned by: | |
---|---|---|---|
Priority: | minor | Milestone: | |
Component: | nginx-module | Version: | 1.18.x |
Keywords: | ssl_ecdh_curve, kex, default_server | Cc: | Avamander |
uname -a: | 5.15.0-78-generic Ubuntu | ||
nginx -V: | nginx version: nginx/1.18.0 (Ubuntu) |
Description (last modified by )
Consider a scenario when a single IP x.y.z.q
has two server blocks. Both server blocks listen on the same port and support TLS. One of those blocks is marked default_server
and handles the non-SNI requests.
If both blocks define ssl_ecdh_curve
then it has zero effect on the non-default_server
. This is done without warning.
One of the possible implications of this is that a more secure configuration is silently ignored. (I stumbled upon this when trying to enable post-quantum key exchange algorithms.)
Understandably nginx can't (currently, even though server_name could be read before KeXs come into play) respect the directive in both blocks, but in that case the ignored one should throw a non-critical warning. Plus, it could be better-documented.
Change History (4)
comment:1 by , 15 months ago
Description: | modified (diff) |
---|
comment:2 by , 14 months ago
comment:3 by , 14 months ago
I guess the default auto
is totally fine in most cases, though when one intentionally does specify a new configuration, it would be better to follow it.
In my case I specifically wanted to enable additional (quantum-resistant) curves for testing and it was really annoying to debug.
Though, this seems very fragile to truly fix and might cause more confusion. I suspect a simple warning when starting the server or in the documentation would suffice in practice.
comment:4 by , 14 months ago
Note that nginx makes no real distinction between name-based virtual servers and IP/port-based virtual servers. Further, the same "server" block can be both name-based and IP-based (for different listening sockets) at the same time. Not to mention that actual behaviour depends on the undocumented aspects of handshake handling within the particular SSL library being used. As such, I'm highly sceptical about warnings. In general, this is not something nginx does for such settings.
General documentation is already present in the article mentioned. It probably can be improved though.
Aspects of how settings are applied to name-based virtual servers are documented in the Virtual server selection section of the Server names article. The general rule is that in name-based virtual servers custom settings might not be used if the particular operation which uses the setting happens before the name is known: in this case settings from the default server for the listening socket apply instead.
In case of SSL handshakes, this is further complicated by the fact that SSL handshakes are handled by the OpenSSL library, and OpenSSL might use settings from the default server even if not strictly required to happen before the name is known. For example, SSL protocol is selected by OpenSSL at a very early stage of the handshake, and it is not possible to change it afterwards, when the name is known (see #676 for details).
In the particular case of ssl_ecdh_curve, things looks as follows:
cert->ecdh_tmp
, and certificates are properly replaced during the SSL context switch in servername callback).SSL_new()
). As such, configuration from the default server applies to all name-based virtual servers. It is possible to re-apply the setting to the connection in the servername callback though (but see below).SSL_new()
). It does, however, work properly with TLSv1.3 when redefined in the servername callback.SSL_new()
). With TLSv1.2, it does work properly when redefined in the servername callback. With TLSv1.3, attempts to redefine the list of curves in the servername callback are ignored, the configuration from the original SSL context is used instead.Overall, it might be possible to improve things by re-applying the list of curves in the servername callback. This might, however, cause degradation of some perfectly valid configurations with TLSv1.3 and OpenSSL. Also, it is not clear if it is actually needed: starting with introduction of curve lists in OpenSSL 1.0.2, I've hardly seen usage of non-default
ssl_ecdh_curves
which actually make sense in production setups.