MEDIUM: quic-be: modify ssl_sock_srv_try_reuse_sess() to reuse backend sessions (0-RTT)

This function is called for both TCP and QUIC connections to reuse SSL sessions
saved by ssl_sess_new_srv_cb() callback called upon new SSL session creation.

In addition to this, a QUIC SSL session must reuse the ALPN and some specific QUIC
transport parameters. This is what is added by this patch for QUIC 0-RTT sessions.

Note that for now on, ssl_sock_srv_try_reuse_sess() may fail for QUIC connections
if it did not managed to reuse the ALPN. The caller must be informed of such an
issue. It must not enable 0-RTT for the current session in this case. This is
impossible without ALPN which is required to start a mux.

ssl_sock_srv_try_reuse_sess() is modified to always succeeds for TCP connections.
This commit is contained in:
Frederic Lecaille 2025-07-31 18:19:24 +02:00
parent 5309dfb56b
commit 6e14365a5b
2 changed files with 41 additions and 2 deletions

View File

@ -71,7 +71,7 @@ int ssl_sock_get_alpn(const struct connection *conn, void *xprt_ctx,
const char **str, int *len);
int ssl_bio_and_sess_init(struct connection *conn, SSL_CTX *ssl_ctx,
SSL **ssl, BIO **bio, BIO_METHOD *bio_meth, void *ctx);
void ssl_sock_srv_try_reuse_sess(struct ssl_sock_ctx *ctx, struct server *srv);
int ssl_sock_srv_try_reuse_sess(struct ssl_sock_ctx *ctx, struct server *srv);
const char *ssl_sock_get_sni(struct connection *conn);
const char *ssl_sock_get_cert_sig(struct connection *conn);
const char *ssl_sock_get_cipher_name(struct connection *conn);

View File

@ -5655,9 +5655,23 @@ int increment_sslconn()
/* Try to reuse an SSL session (SSL_SESSION object) for <srv> server with <ctx>
* as SSL socket context.
* Return 1 if succeeded, 0 if not. Always succeeds for TCP socket. May fail
* for QUIC sockets.
*/
void ssl_sock_srv_try_reuse_sess(struct ssl_sock_ctx *ctx, struct server *srv)
int ssl_sock_srv_try_reuse_sess(struct ssl_sock_ctx *ctx, struct server *srv)
{
#ifdef USE_QUIC
struct quic_conn *qc = ctx->qc;
/* Default status for QUIC sockets + 0-RTT is failure(0). The status will
* be set to success(1) only if the QUIC connection parameters
* (transport parameters and ALPN) are successfully reused.
*/
int ret = qc && (srv->ssl_ctx.options & SRV_SSL_O_EARLY_DATA) ? 0 : 1;
#else
/* Always succeeds for TCP sockets. */
int ret = 1;
#endif
HA_RWLOCK_RDLOCK(SSL_SERVER_LOCK, &srv->ssl_ctx.lock);
if (srv->ssl_ctx.reused_sess[tid].ptr) {
/* let's recreate a session from (ptr,size) and assign
@ -5686,6 +5700,16 @@ void ssl_sock_srv_try_reuse_sess(struct ssl_sock_ctx *ctx, struct server *srv)
HA_RWLOCK_RDLOCK(SSL_SERVER_LOCK, &srv->ssl_ctx.reused_sess[tid].sess_lock);
if (srv->ssl_ctx.reused_sess[tid].sni)
SSL_set_tlsext_host_name(ctx->ssl, srv->ssl_ctx.reused_sess[tid].sni);
#ifdef USE_QUIC
if (qc && srv->ssl_ctx.options & SRV_SSL_O_EARLY_DATA) {
unsigned char *alpn = (unsigned char *)srv->path_params.nego_alpn;
struct quic_early_transport_params *etps = &srv->path_params.tps;
if (quic_reuse_srv_params(qc, alpn, etps))
/* Success */
ret = 1;
}
#endif
HA_RWLOCK_RDUNLOCK(SSL_SERVER_LOCK, &srv->ssl_ctx.reused_sess[tid].sess_lock);
}
} else {
@ -5708,6 +5732,16 @@ void ssl_sock_srv_try_reuse_sess(struct ssl_sock_ctx *ctx, struct server *srv)
if (sess) {
if (!SSL_set_session(ctx->ssl, sess))
HA_ATOMIC_CAS(&srv->ssl_ctx.last_ssl_sess_tid, &old_tid, 0); // no more valid
#ifdef USE_QUIC
else if (qc && srv->ssl_ctx.options & SRV_SSL_O_EARLY_DATA) {
unsigned char *alpn = (unsigned char *)srv->path_params.nego_alpn;
struct quic_early_transport_params *etps = &srv->path_params.tps;
if (quic_reuse_srv_params(qc, alpn, etps))
/* Success */
ret = 1;
}
#endif
SSL_SESSION_free(sess);
}
}
@ -5719,6 +5753,8 @@ void ssl_sock_srv_try_reuse_sess(struct ssl_sock_ctx *ctx, struct server *srv)
}
}
HA_RWLOCK_RDUNLOCK(SSL_SERVER_LOCK, &srv->ssl_ctx.lock);
return ret;
}
/*
@ -5766,6 +5802,9 @@ static int ssl_sock_init(struct connection *conn, void **xprt_ctx)
#ifdef HA_USE_KTLS
ctx->record_type = 0;
#endif
#ifdef USE_QUIC
ctx->qc = NULL;
#endif
next_sslconn = increment_sslconn();
if (!next_sslconn) {