]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MEDIUM: tcpcheck/backend: Get the connection SNI before initializing SSL ctx
authorChristopher Faulet <cfaulet@haproxy.com>
Fri, 5 Dec 2025 10:10:53 +0000 (11:10 +0100)
committerChristopher Faulet <cfaulet@haproxy.com>
Mon, 8 Dec 2025 14:22:01 +0000 (15:22 +0100)
The SNI of a new connection is now retrieved earlier, before the
initialization of the SSL context. So, concretely, it is now performed
before calling conn_prepare(). The SNI is then set just after.

src/backend.c
src/tcpcheck.c

index d84a5f52474e684fd4c1a287e932c9093c1f67bd..9722b71b9a78db56aba7a121081a36dbde75b026 100644 (file)
@@ -2037,11 +2037,31 @@ int connect_server(struct stream *s)
 
                if (srv) {
                        struct protocol *proto = protocol_lookup(srv_conn->dst->ss_family, srv->addr_type.proto_type, srv->alt_proto);
+#ifdef USE_OPENSSL
+                       struct sample *sni_smp = NULL;
+                       struct ist sni = IST_NULL;
+
+                       /* Set socket SNI */
+                       if (srv->xprt && srv->xprt->get_ssl_sock_ctx && srv->ssl_ctx.sni) {
+                               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)) {
+                                       sni = ist2(b_orig(&sni_smp->data.u.str), b_data(&sni_smp->data.u.str));
+                                       srv_conn->sni_hash = ssl_sock_sni_hash(sni);
+                               }
+                       }
+#endif /* USE_OPENSSL */
 
                        if (conn_prepare(srv_conn, proto, srv->xprt)) {
                                conn_free(srv_conn);
                                return SF_ERR_INTERNAL;
                        }
+#ifdef USE_OPENSSL
+                       if (isttest(sni))
+                               ssl_sock_set_servername(srv_conn, istptr(sni));
+
+#endif
                } else if (obj_type(s->target) == OBJ_TYPE_PROXY) {
                        int ret;
 
@@ -2154,22 +2174,6 @@ int connect_server(struct stream *s)
        if (err != SF_ERR_NONE)
                return err;
 
-#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)) {
-                       srv_conn->sni_hash = ssl_sock_sni_hash(ist2(b_orig(&sni_smp->data.u.str),
-                                                                   b_data(&sni_smp->data.u.str)));
-                       ssl_sock_set_servername(srv_conn, sni_smp->data.u.str.area);
-               }
-       }
-#endif /* USE_OPENSSL */
-
        /* The CO_FL_SEND_PROXY flag may have been set by the connect method,
         * if so, add our handshake pseudo-XPRT now.
         */
index d0fd31cfe1d4ffd8d064c2e0a45b8074c1d31a0f..97b909ea661c2a5b51fc31196e2f5b9a62832792 100644 (file)
@@ -1459,6 +1459,20 @@ enum tcpcheck_eval_ret tcpcheck_eval_connect(struct check *check, struct tcpchec
                ? xprt_get(XPRT_SSL)
                : ((connect->options & TCPCHK_OPT_DEFAULT_CONNECT) ? check->xprt : xprt_get(XPRT_RAW)));
 
+#ifdef USE_OPENSSL
+       if (xprt && xprt->get_ssl_sock_ctx) {
+               if (connect->sni)
+                       sni = ist(connect->sni);
+               else if ((connect->options & TCPCHK_OPT_DEFAULT_CONNECT) && s && s->check.sni)
+                       sni = ist(s->check.sni);
+               else if (auto_sni)
+                       sni = ist2(b_orig(auto_sni), b_data(auto_sni));
+
+               if (isttest(sni))
+                       conn->sni_hash = ssl_sock_sni_hash(sni);
+       }
+#endif
+
        if (conn_prepare(conn, proto, xprt) < 0) {
                TRACE_ERROR("xprt allocation error", CHK_EV_TCPCHK_CONN|CHK_EV_TCPCHK_ERR, check);
                status = SF_ERR_RESOURCE;
@@ -1506,17 +1520,8 @@ enum tcpcheck_eval_ret tcpcheck_eval_connect(struct check *check, struct tcpchec
 
 #ifdef USE_OPENSSL
        if (conn_is_ssl(conn)) {
-               if (connect->sni)
-                       sni = ist(connect->sni);
-               else if ((connect->options & TCPCHK_OPT_DEFAULT_CONNECT) && s && s->check.sni)
-                       sni = ist(s->check.sni);
-               else if (auto_sni)
-                       sni = ist2(b_orig(auto_sni), b_data(auto_sni));
-
-               if (isttest(sni)) {
-                       conn->sni_hash = ssl_sock_sni_hash(sni);
+               if (isttest(sni))
                        ssl_sock_set_servername(conn, istptr(sni));
-               }
 
                if (connect->alpn)
                        ssl_sock_set_alpn(conn, (unsigned char *)connect->alpn, connect->alpn_len);