]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
BUG/MEDIUM: server/ssl: Unset the SNI for new server connections if none is set
authorChristopher Faulet <cfaulet@haproxy.com>
Mon, 24 Nov 2025 13:41:54 +0000 (14:41 +0100)
committerChristopher Faulet <cfaulet@haproxy.com>
Tue, 25 Nov 2025 15:32:46 +0000 (16:32 +0100)
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.

src/backend.c
src/tcpcheck.c

index 0170547b29274620444471a63937a63102269372..45dab68df69c05b6c59e03e8309c9f4a6c7b11d6 100644 (file)
@@ -2156,14 +2156,22 @@ int connect_server(struct stream *s)
 
 #ifdef USE_OPENSSL
        /* Set socket SNI unless connection is reused. */
-       if (conn_is_ssl(srv_conn) && srv && srv->ssl_ctx.sni && !(s->flags & SF_SRV_REUSED)) {
-               struct sample *sni_smp = NULL;
-
-               sni_smp = sample_fetch_as_type(s->be, s->sess, s,
-                                              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);
+       if (conn_is_ssl(srv_conn) && !(s->flags & SF_SRV_REUSED)) {
+               int sni_set = 0;
+
+               if (srv && srv->ssl_ctx.sni) {
+                       struct sample *sni_smp = NULL;
+
+                       sni_smp = sample_fetch_as_type(s->be, s->sess, s,
+                                                      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 */
 
index 815a84099c80f38f9dddff50a8b2b7f6c97199d7..88a54d1486f5a2ed3be198e8aecebff2c12b4905 100644 (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);
                else if (auto_sni)
                        ssl_sock_set_servername(conn, b_orig(auto_sni));
+               else
+                       ssl_sock_set_servername(conn, NULL);
 
                if (connect->alpn)
                        ssl_sock_set_alpn(conn, (unsigned char *)connect->alpn, connect->alpn_len);