BUG/MEDIUM: server/ssl: Unset the SNI for new server connections if none is set

When a new SSL server connection is created, if no SNI is set, it is
possible to inherit from the one of the reused TLS session. The bug was
introduced by the commit 95ac5fe4a ("MEDIUM: ssl_sock: always use the SSL's
server name, not the one from the tid"). The mixup is possible between
regular connections but also with health-checks connections.

To fix the issue, when no SNI is set, for regular server connections and for
health-check connections, the SNI must explicitly be disabled by calling
ssl_sock_set_servername() with the hostname set to NULL.

Many thanks to Lukas for his detailed bug report.

This patch should fix the issue #3195. It must be backported as far as 3.0.
This commit is contained in:
Christopher Faulet 2025-11-24 14:41:54 +01:00
parent a70816da82
commit de29000e60
2 changed files with 17 additions and 7 deletions

View File

@ -2156,14 +2156,22 @@ int connect_server(struct stream *s)
#ifdef USE_OPENSSL #ifdef USE_OPENSSL
/* Set socket SNI unless connection is reused. */ /* Set socket SNI unless connection is reused. */
if (conn_is_ssl(srv_conn) && srv && srv->ssl_ctx.sni && !(s->flags & SF_SRV_REUSED)) { if (conn_is_ssl(srv_conn) && !(s->flags & SF_SRV_REUSED)) {
struct sample *sni_smp = NULL; int sni_set = 0;
sni_smp = sample_fetch_as_type(s->be, s->sess, s, if (srv && srv->ssl_ctx.sni) {
SMP_OPT_DIR_REQ | SMP_OPT_FINAL, struct sample *sni_smp = NULL;
srv->ssl_ctx.sni, SMP_T_STR);
if (smp_make_safe(sni_smp)) sni_smp = sample_fetch_as_type(s->be, s->sess, s,
ssl_sock_set_servername(srv_conn, sni_smp->data.u.str.area); SMP_OPT_DIR_REQ | SMP_OPT_FINAL,
srv->ssl_ctx.sni, SMP_T_STR);
if (smp_make_safe(sni_smp)) {
ssl_sock_set_servername(srv_conn, sni_smp->data.u.str.area);
sni_set = 1;
}
}
if (!sni_set)
ssl_sock_set_servername(srv_conn, NULL);
} }
#endif /* USE_OPENSSL */ #endif /* USE_OPENSSL */

View File

@ -1509,6 +1509,8 @@ enum tcpcheck_eval_ret tcpcheck_eval_connect(struct check *check, struct tcpchec
ssl_sock_set_servername(conn, s->check.sni); ssl_sock_set_servername(conn, s->check.sni);
else if (auto_sni) else if (auto_sni)
ssl_sock_set_servername(conn, b_orig(auto_sni)); ssl_sock_set_servername(conn, b_orig(auto_sni));
else
ssl_sock_set_servername(conn, NULL);
if (connect->alpn) if (connect->alpn)
ssl_sock_set_alpn(conn, (unsigned char *)connect->alpn, connect->alpn_len); ssl_sock_set_alpn(conn, (unsigned char *)connect->alpn, connect->alpn_len);