]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: quic-be: Save the backend 0-RTT parameters
authorFrederic Lecaille <flecaille@haproxy.com>
Thu, 31 Jul 2025 15:56:02 +0000 (17:56 +0200)
committerFrederic Lecaille <flecaille@haproxy.com>
Tue, 4 Nov 2025 10:09:36 +0000 (11:09 +0100)
For both TCP and QUIC connections, this is ssl_sess_new_srv_cb() callback which
is called when a new SSL session is created. Its role is to save the session to
be reused for the next sessions.

This patch modifies this callback to save the QUIC parameters to be reused
for the next 0-RTT sessions (or during SSL session resumption).

A new ->alpn member is added to the reused_sess objects allocated by thread
and server alongsise ->tps new quic_early_transport_params struct used to
save the QUIC transport parameters to be reused for 0-RTT sessions.

include/haproxy/server-t.h
src/ssl_sock.c

index e2036c9c76ff61b3398be1a83ce4e445b49caa80..74f357ece268849ea343e85a51721f95daa48d20 100644 (file)
@@ -479,6 +479,10 @@ struct server {
                        int size;
                        int allocated_size;
                        char *sni; /* SNI used for the session */
+#ifdef USE_QUIC
+                       struct quic_early_transport_params tps;
+                       char *alpn;
+#endif
                        __decl_thread(HA_RWLOCK_T sess_lock);
                } * reused_sess;
 
index 0cdd6c77e06f9dad148ec9e13fd30e7cbd230250..15c1caa48e49c8b6ec791788a405354adadf0447 100644 (file)
@@ -4181,6 +4181,9 @@ static int ssl_sess_new_srv_cb(SSL *ssl, SSL_SESSION *sess)
                int len;
                unsigned char *ptr;
                const char *sni;
+#ifdef USE_QUIC
+               struct quic_conn *qc = SSL_get_ex_data(ssl, ssl_qc_app_data_index);
+#endif
 
                /* determine the required len to store this new session */
                len = i2d_SSL_SESSION(sess, NULL);
@@ -4233,6 +4236,31 @@ static int ssl_sess_new_srv_cb(SSL *ssl, SSL_SESSION *sess)
                        /* if there wasn't an old sni but there is a new one */
                        s->ssl_ctx.reused_sess[tid].sni = strdup(sni);
                }
+#ifdef USE_QUIC
+               /* The selected ALPN is not stored without SSL session. */
+               if (qc && (s->ssl_ctx.options & SRV_SSL_O_EARLY_DATA) &&
+                   s->ssl_ctx.reused_sess[tid].ptr) {
+                       const char *alpn = NULL;
+                       int alpn_len;
+
+                       if (ssl_sock_get_alpn(conn, qc->xprt_ctx, &alpn, &alpn_len)) {
+                               char **alpn_addr = &s->ssl_ctx.reused_sess[tid].alpn;
+                               struct quic_early_transport_params *etps =
+                                       &s->ssl_ctx.reused_sess[tid].tps;
+
+                               /* <*alpn_addr> is a NULL terminated string */
+                               if (*alpn_addr == NULL ||
+                                   alpn_len != strlen(*alpn_addr) ||
+                                   memcmp(*alpn_addr, alpn, alpn_len) != 0) {
+                                       ha_free(alpn_addr);
+                                       *alpn_addr = my_strndup((const char *)alpn, alpn_len);
+                                       /* The transport parameters are not stored without ALPN */
+                                       if (*alpn_addr)
+                                               qc_early_transport_params_cpy(qc, etps, &qc->tx.params);
+                               }
+                       }
+               }
+#endif
                HA_RWLOCK_WRUNLOCK(SSL_SERVER_LOCK, &s->ssl_ctx.reused_sess[tid].sess_lock);
                HA_RWLOCK_RDUNLOCK(SSL_SERVER_LOCK, &s->ssl_ctx.lock);
        } else {
@@ -4241,6 +4269,9 @@ static int ssl_sess_new_srv_cb(SSL *ssl, SSL_SESSION *sess)
                if (s->ssl_ctx.reused_sess[tid].ptr) {
                        HA_RWLOCK_WRLOCK(SSL_SERVER_LOCK, &s->ssl_ctx.reused_sess[tid].sess_lock);
                        ha_free(&s->ssl_ctx.reused_sess[tid].ptr);
+#ifdef USE_QUIC
+                       ha_free(&s->ssl_ctx.reused_sess[tid].alpn);
+#endif
                        HA_RWLOCK_WRUNLOCK(SSL_SERVER_LOCK, &s->ssl_ctx.reused_sess[tid].sess_lock);
                }
 
@@ -5432,6 +5463,9 @@ void ssl_sock_free_srv_ctx(struct server *srv)
                for (i = 0; i < global.nbthread; i++) {
                        ha_free(&srv->ssl_ctx.reused_sess[i].ptr);
                        ha_free(&srv->ssl_ctx.reused_sess[i].sni);
+#ifdef USE_QUIC
+                       ha_free(&srv->ssl_ctx.reused_sess[i].alpn);
+#endif
                }
                ha_free(&srv->ssl_ctx.reused_sess);
        }