From: Willy Tarreau Date: Wed, 29 Oct 2025 07:03:01 +0000 (+0100) Subject: MINOR: ssl-sample: add ssl_fc_early_rcvd() to detect use of early data X-Git-Tag: v3.3-dev11~24 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=18b27bfec948126f628a026c1e02f9e0421c569d;p=thirdparty%2Fhaproxy.git MINOR: ssl-sample: add ssl_fc_early_rcvd() to detect use of early data We currently have ssl_fc_has_early() which says that early data are still unconfirmed by a final handshake, but nothing to see if a client has been able to use early data at all, which is a problem because such mechanisms generally depend on multiple factors and it's hard to know when they start to work. This new sample fetch function will indicate that some early data were seen over that front connection, i.e. this can be used to confirm that at some point the client was able to push some. This is essentially a debugging tool that has no practical use case other than debugging. --- diff --git a/doc/configuration.txt b/doc/configuration.txt index 4bcf4ea6b..136a7b749 100644 --- a/doc/configuration.txt +++ b/doc/configuration.txt @@ -25028,6 +25028,15 @@ ssl_fc_curve : string connection was made over an SSL/TLS transport layer. This requires OpenSSL >= 3.0.0. +ssl_fc_early_rcvd : boolean + Returns true if early data were seen over that connection, regardless of the + fact that the handshake has since completed. It has no practical use case for + traffic processing, however it's about the only way to "see" that a client + used 0-RTT to send early data, and is sometimes useful when debugging, since + the only other alternatives are network traffic captures or logging the front + connection's flags and matching them in the code. It may also be useful to + get statistics on clients' capabilities. See also "ssl_fc_has_early". + ssl_fc_early_exporter_secret : string Return the EARLY_EXPORTER_SECRET as an hexadecimal string for the front connection when the incoming connection was made over an TLS 1.3 @@ -25133,7 +25142,8 @@ ssl_fc_has_crt : boolean ssl_fc_has_early : boolean Returns true if early data were sent, and the handshake didn't complete yet. As it has security implications, it is useful to be able to refuse those, or - wait until the handshake completes (via the "wait-for-handshake" action). + wait until the handshake completes (via the "wait-for-handshake" action). See + also "ssl_fc_early_rcvd". ssl_fc_has_sni : boolean This checks for the presence of a Server Name Indication TLS extension (SNI) diff --git a/src/ssl_sample.c b/src/ssl_sample.c index c64522d24..4746b8c0c 100644 --- a/src/ssl_sample.c +++ b/src/ssl_sample.c @@ -574,6 +574,27 @@ smp_fetch_ssl_fc_has_early(const struct arg *args, struct sample *smp, const cha return 1; } +static int +smp_fetch_ssl_fc_early_rcvd(const struct arg *args, struct sample *smp, const char *kw, void *private) +{ + SSL *ssl; + struct connection *conn; + + conn = objt_conn(smp->sess->origin); + ssl = ssl_sock_get_ssl_object(conn); + if (!ssl) + return 0; + + smp->flags = 0; + smp->data.type = SMP_T_BOOL; +#ifdef OPENSSL_IS_BORINGSSL + smp->data.u.sint = SSL_early_data_accepted(ssl); +#else + smp->data.u.sint = !!(conn->flags & CO_FL_EARLY_DATA); +#endif + return 1; +} + /* boolean, returns true if client cert was present */ static int smp_fetch_ssl_fc_has_crt(const struct arg *args, struct sample *smp, const char *kw, void *private) @@ -2515,6 +2536,7 @@ static struct sample_fetch_kw_list sample_fetch_keywords = {ILH, { #if (HA_OPENSSL_VERSION_NUMBER >= 0x3000000fL) { "ssl_fc_curve", smp_fetch_ssl_fc_ec, 0, NULL, SMP_T_STR, SMP_USE_L5CLI }, #endif + { "ssl_fc_early_rcvd", smp_fetch_ssl_fc_early_rcvd, 0, NULL, SMP_T_BOOL, SMP_USE_L5CLI }, { "ssl_fc_has_crt", smp_fetch_ssl_fc_has_crt, 0, NULL, SMP_T_BOOL, SMP_USE_L5CLI }, { "ssl_fc_has_early", smp_fetch_ssl_fc_has_early, 0, NULL, SMP_T_BOOL, SMP_USE_L5CLI }, { "ssl_fc_has_sni", smp_fetch_ssl_fc_has_sni, 0, NULL, SMP_T_BOOL, SMP_USE_L5CLI },