BUG/MINOR: quic: SSL counters not handled

The SSL counters were not handled at all for QUIC connections. This patch
implement ssl_sock_update_counters() extracting the code from ssl_sock.c
and call this function where applicable both in TLS/TCP and QUIC parts.

Must be backported as far as 2.8.
This commit is contained in:
Frederic Lecaille 2025-10-17 12:07:10 +02:00
parent 8a8417b54a
commit 51eca5cbce
3 changed files with 55 additions and 22 deletions

View File

@ -86,6 +86,9 @@ int ssl_sock_get_remote_common_name(struct connection *conn,
struct buffer *out);
int ssl_sock_get_pkey_algo(struct connection *conn, struct buffer *out);
unsigned int ssl_sock_get_verify_result(struct connection *conn);
void ssl_sock_update_counters(SSL *ssl,
struct ssl_counters *counters,
struct ssl_counters *counters_px, int backend);
#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
int ssl_sock_update_tlskey_ref(struct tls_keys_ref *ref,
struct buffer *tlskey);

View File

@ -8,6 +8,7 @@
#include <haproxy/quic_tp.h>
#include <haproxy/quic_trace.h>
#include <haproxy/ssl_sock.h>
#include <haproxy/stats.h>
#include <haproxy/trace.h>
DECLARE_TYPED_POOL(pool_head_quic_ssl_sock_ctx, "quic_ssl_sock_ctx", struct ssl_sock_ctx);
@ -853,12 +854,28 @@ static forceinline void qc_ssl_dump_errors(struct connection *conn)
int qc_ssl_do_hanshake(struct quic_conn *qc, struct ssl_sock_ctx *ctx)
{
int ret, ssl_err, state;
struct ssl_counters *counters = NULL;
struct ssl_counters *counters_px = NULL;
TRACE_ENTER(QUIC_EV_CONN_SSLDATA, qc);
ret = 0;
ssl_err = SSL_ERROR_NONE;
state = qc->state;
if (!qc_is_back(qc)) {
counters = EXTRA_COUNTERS_GET(qc->li->extra_counters, &ssl_stats_module);
counters_px = EXTRA_COUNTERS_GET(qc->li->bind_conf->frontend->extra_counters_fe,
&ssl_stats_module);
}
else if (ctx->conn) {
struct server *srv = __objt_server(ctx->conn->target);
counters = EXTRA_COUNTERS_GET(srv->extra_counters, &ssl_stats_module);
counters_px = EXTRA_COUNTERS_GET(srv->proxy->extra_counters_be,
&ssl_stats_module);
}
if (state < QUIC_HS_ST_COMPLETE) {
ssl_err = SSL_do_handshake(ctx->ssl);
TRACE_PROTO("SSL_do_handshake() called", QUIC_EV_CONN_IO_CB, qc, NULL, NULL, ctx->ssl);
@ -928,6 +945,7 @@ int qc_ssl_do_hanshake(struct quic_conn *qc, struct ssl_sock_ctx *ctx)
#ifndef HAVE_OPENSSL_QUIC
TRACE_PROTO("SSL handshake OK", QUIC_EV_CONN_IO_CB, qc, &state);
ssl_sock_update_counters(ctx->ssl, counters, counters_px, qc_is_back(qc));
#else
/* Hack to support O-RTT with the OpenSSL 3.5 QUIC API.
* SSL_do_handshake() succeeds at the first call. Why? |-(
@ -946,6 +964,7 @@ int qc_ssl_do_hanshake(struct quic_conn *qc, struct ssl_sock_ctx *ctx)
}
else {
TRACE_PROTO("SSL handshake OK", QUIC_EV_CONN_IO_CB, qc, &state);
ssl_sock_update_counters(ctx->ssl, counters, counters_px, qc_is_back(qc));
}
}
#endif

View File

@ -5550,6 +5550,37 @@ err:
return -1;
}
/* Update <counters> counters and <counters_px> proxy counters of frontends or
* backends with <ssl> as SSL connection object, depending on <backend> boolean
* value.
*/
void ssl_sock_update_counters(SSL *ssl,
struct ssl_counters *counters,
struct ssl_counters *counters_px,
int backend)
{
if (!SSL_session_reused(ssl)) {
if (backend) {
update_freq_ctr(&global.ssl_be_keys_per_sec, 1);
if (global.ssl_be_keys_per_sec.curr_ctr > global.ssl_be_keys_max)
global.ssl_be_keys_max = global.ssl_be_keys_per_sec.curr_ctr;
}
else {
update_freq_ctr(&global.ssl_fe_keys_per_sec, 1);
if (global.ssl_fe_keys_per_sec.curr_ctr > global.ssl_fe_keys_max)
global.ssl_fe_keys_max = global.ssl_fe_keys_per_sec.curr_ctr;
}
if (counters) {
HA_ATOMIC_INC(&counters->sess);
HA_ATOMIC_INC(&counters_px->sess);
}
}
else if (counters) {
HA_ATOMIC_INC(&counters->reused_sess);
HA_ATOMIC_INC(&counters_px->reused_sess);
}
}
/* This is the callback which is used when an SSL handshake is pending. It
* updates the FD status if it wants some polling before being called again.
@ -5564,7 +5595,7 @@ static int ssl_sock_handshake(struct connection *conn, unsigned int flag)
struct ssl_counters *counters = NULL;
struct ssl_counters *counters_px = NULL;
struct listener *li;
struct server *srv;
struct server *srv = NULL;
socklen_t lskerr;
int skerr;
@ -5883,27 +5914,7 @@ reneg_ok:
SSL_clear_mode(ctx->ssl, SSL_MODE_ASYNC);
#endif
/* Handshake succeeded */
if (!SSL_session_reused(ctx->ssl)) {
if (objt_server(conn->target)) {
update_freq_ctr(&global.ssl_be_keys_per_sec, 1);
if (global.ssl_be_keys_per_sec.curr_ctr > global.ssl_be_keys_max)
global.ssl_be_keys_max = global.ssl_be_keys_per_sec.curr_ctr;
}
else {
update_freq_ctr(&global.ssl_fe_keys_per_sec, 1);
if (global.ssl_fe_keys_per_sec.curr_ctr > global.ssl_fe_keys_max)
global.ssl_fe_keys_max = global.ssl_fe_keys_per_sec.curr_ctr;
}
if (counters) {
HA_ATOMIC_INC(&counters->sess);
HA_ATOMIC_INC(&counters_px->sess);
}
}
else if (counters) {
HA_ATOMIC_INC(&counters->reused_sess);
HA_ATOMIC_INC(&counters_px->reused_sess);
}
ssl_sock_update_counters(ctx->ssl, counters, counters_px, !!srv);
TRACE_LEAVE(SSL_EV_CONN_HNDSHK, conn, ctx->ssl);