Opened 3 years ago

Closed 3 years ago

Last modified 3 years ago

#1088 closed enhancement (fixed)

Add variable $ssl_dhe (possible values: curve name or dh<keylength>, e.g. dh3072 etc.)

Reported by: Darkudorus@… Owned by:
Priority: minor Milestone:
Component: nginx-module Version:
Keywords: ngx_http_ssl_module ssl Cc:
uname -a: irrelevant
nginx -V: irrelevant

Description

It would be helpful to monitor the use of curves (with ECDHE) or the length of dh parameters (with DHE) in access log or for Lua. $ssl_cipher and $ssl_protocol are not precise enough.

Values should be an OpenSSL curve name, or "dh<length>" (dh2048, dh4096 etc.).
So my proposal would be $ssl_dhe instead of something like $ssl_curve to cover both ECDHE and DHE.

Thank you.

Change History (9)

comment:1 by Maxim Dounin, 3 years ago

Milestone: 1.11.5

Not sure if it's at all possible from server point of view. Recent versions of OpenSSL (1.0.2+) provide SSL_get_server_tmp_key() function for similar tasks (used by openssl s_client), but it can be only used by clients and doesn't work for servers.

comment:3 by bblack.wikimedia.org@…, 3 years ago

FWIW, we hacked up a local nginx-1.11 patch to log ECDHE curve choice (but not DHE), without upstream changes in OpenSSL. Works on at least OpenSSL 1.0.2 and 1.1.0b. Feel free to steal it or improve it! :)

https://github.com/wikimedia/operations-software-nginx/commit/5d8b88cadbab91da6dd4f9ef6d86addd0f955c7e

We're using it to track the shift from NIST P-256 to x25519 as we progressively roll out OpenSSL-1.1 (starting yesterday), see the "ECDHE Curves" graph here:

https://grafana.wikimedia.org/dashboard/db/tls-ciphers

comment:4 by bblack.wikimedia.org@…, 3 years ago

Update on the above: I finally got around to digging into why the stats looked anomalous compared to e.g. chacha20. The patch above only gives the correct result for requests in a fresh session, not in a resumed session (and will indicate X25519 w/ OpenSSL-1.1.0 on a resume of any ECDHE curve).

The problem with resumed sessions run deep: technically, ECDHE isn't actually used for the resumption (thus OpenSSL doesn't need the info, and the client doesn't send it I don't think), and OpenSSL doesn't serialize the client curve preference list to the ASN.1 representation of a session, either.

So, you can use a simple approach as above as long as you're careful to only log on non-resumed sessions. For various reasons related to statistics sanity, we prefer to log connection properties per-request and regardless of session-reuse, so for that we have to keep the client's curve list (or server's decision, either way) with the session data somehow.

It would be preferably if OpenSSL added them to the ASN.1 (they're in the C-level session struct already), but for now I'm trying out using an even-hackier-than-above nginx patch to save the curve choice in nginx's session data. It feels ugly but it seems to work for now: https://github.com/wikimedia/operations-software-nginx/blob/wmf-1.11.4/debian/patches/0500-ssl-curve.patch

comment:5 by Maxim Dounin, 3 years ago

Note that the patch to save the curve choice in nginx's session data won't work for session tickets. Unless tickets are explicitly disabled I would expect it to produce highly inconsistent results.

Overall, I tend to think that just listing all curves supported by a client might be a better option. On the other hand it is likely to have the same problem as SSL_get1_curves() uses the same list of curves as stored in the session, and not a real list from ClientHello.

comment:6 by Maxim Dounin, 3 years ago

Keywords: ssl added

comment:7 by Maxim Dounin <mdounin@…>, 3 years ago

In 6817:e75e854657ba/nginx:

SSL: $ssl_curves (ticket #1088).

The variable contains a list of curves as supported by the client.
Known curves are listed by their names, unknown ones are shown
in hex, e.g., "0x001d:prime256v1:secp521r1:secp384r1".

Note that OpenSSL uses session data for SSL_get1_curves(), and
it doesn't store full list of curves supported by the client when
serializing a session. As a result $ssl_curves is only available
for new sessions (and will be empty for reused ones).

The variable is only meaningful when using OpenSSL 1.0.2 and above.
With older versions the variable is empty.

comment:8 by Maxim Dounin, 3 years ago

Resolution: fixed
Status: newclosed

in reply to:  2 comment:9 by TerraX-net@…, 3 years ago

Replying to Darkudorus@…:

https://github.com/openssl/openssl/issues/1656

For anyone seeing this later: I meaned FFDHE groups (TLS 1.3) for DHE. (I think I should open a new ticket when OpenSSL finally has TLS 1.3 support.)

Thank you very much for implementing this!

Note: See TracTickets for help on using tickets.