]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
BUG/MINOR: quic: SSL counters not handled
authorFrederic Lecaille <flecaille@haproxy.com>
Fri, 17 Oct 2025 10:07:10 +0000 (12:07 +0200)
committerFrederic Lecaille <flecaille@haproxy.com>
Fri, 17 Oct 2025 10:13:43 +0000 (12:13 +0200)
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.

include/haproxy/ssl_sock.h
src/quic_ssl.c
src/ssl_sock.c

index d885a1ba0ae0f437f1ba8f14e225cbedc2875e56..4658ab9c6486a86cb85fe69d03306d8e5371a030 100644 (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);
index 60e79a5166faa29b4840846bec75b0f2b8158db8..31220ff77b9eb781c2caaa2580fd302bf997e180 100644 (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
index 8099f0d9684fe5f13d671b315c29045dc46e3383..d643586415d8ee2ffdd291663d4d80c81da36dad 100644 (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);