]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: connection/ssl: Store the SNI hash value in the connection itself
authorChristopher Faulet <cfaulet@haproxy.com>
Fri, 5 Dec 2025 10:04:21 +0000 (11:04 +0100)
committerChristopher Faulet <cfaulet@haproxy.com>
Mon, 8 Dec 2025 14:22:01 +0000 (15:22 +0100)
When a SNI is set on a new connection, its hash is now saved in the
connection itself. To do so, a dedicated field was added into the connection
strucutre, called sni_hash. For now, this value is only used when the TLS
session is cached.

include/haproxy/connection-t.h
src/backend.c
src/connection.c
src/ssl_sock.c
src/tcpcheck.c

index a603966e5612ac7009f91794e42a4528963cd8e5..b727c3a56f51dddb98e75f91df25746b0f030ba8 100644 (file)
@@ -660,6 +660,7 @@ struct connection {
                struct buffer name;    /* Only used for passive reverse. Used as SNI when connection added to server idle pool. */
        } reverse;
 
+       uint64_t sni_hash;             /* Hash of the SNI. Used to cache the TLS session and try to reuse it. set to 0 is there is no SNI */
        uint32_t term_evts_log;        /* Termination events log: first 4 events reported from fd, handshake or xprt */
        uint32_t mark;                 /* set network mark, if CO_FL_OPT_MARK is set */
        uint8_t tos;                   /* set ip tos, if CO_FL_OPT_TOS is set */
index 0170547b29274620444471a63937a63102269372..d84a5f52474e684fd4c1a287e932c9093c1f67bd 100644 (file)
@@ -2162,8 +2162,11 @@ int connect_server(struct stream *s)
                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))
+               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 */
 
index ed3764df5a4bba3dd30a12b42615d0715926fc1b..445991421c2e44fec0d9966064fb2b4773d23bc9 100644 (file)
@@ -520,6 +520,7 @@ void conn_init(struct connection *conn, void *target)
        conn->xprt = NULL;
        conn->reverse.target = NULL;
        conn->reverse.name = BUF_NULL;
+       conn->sni_hash = 0;
 }
 
 /* Initialize members used for backend connections.
index d3eabacdaa64604dc4444b4098b3338fc035b907..880bb2bd9f398523701d899e2f4406e473d66930 100644 (file)
@@ -4202,7 +4202,6 @@ static int ssl_sess_new_srv_cb(SSL *ssl, SSL_SESSION *sess)
                int len;
                unsigned char *ptr;
                const char *sni;
-               uint64_t sni_hash;
 #ifdef USE_QUIC
                struct quic_conn *qc = SSL_get_ex_data(ssl, ssl_qc_app_data_index);
 #endif
@@ -4247,11 +4246,10 @@ static int ssl_sess_new_srv_cb(SSL *ssl, SSL_SESSION *sess)
                else if (s->ssl_ctx.reused_sess[tid].ptr && !old_tid)
                        HA_ATOMIC_CAS(&s->ssl_ctx.last_ssl_sess_tid, &old_tid, tid + 1);
 
-               sni_hash = (sni ? ssl_sock_sni_hash(ist(sni)) : 0);
-               if (s->ssl_ctx.reused_sess[tid].sni_hash != sni_hash) {
-                       /* if the new sni hash isn' t the same as the old one */
-                       s->ssl_ctx.reused_sess[tid].sni_hash = sni_hash;
+               if (s->ssl_ctx.reused_sess[tid].sni_hash != conn->sni_hash) {
+                       /* if the new sni hash or isn' t the same as the old one */
                        ha_free(&s->ssl_ctx.reused_sess[tid].sni);
+                       s->ssl_ctx.reused_sess[tid].sni_hash = conn->sni_hash;
                        if (sni)
                                s->ssl_ctx.reused_sess[tid].sni = strdup(sni);
                }
index 815a84099c80f38f9dddff50a8b2b7f6c97199d7..d0fd31cfe1d4ffd8d064c2e0a45b8074c1d31a0f 100644 (file)
@@ -1280,6 +1280,9 @@ enum tcpcheck_eval_ret tcpcheck_eval_connect(struct check *check, struct tcpchec
        struct buffer *auto_sni = NULL;
        int status, port;
        int check_type;
+#ifdef USE_OPENSSL
+       struct ist sni = IST_NULL;
+#endif
 
        TRACE_ENTER(CHK_EV_TCPCHK_CONN, check);
 
@@ -1504,11 +1507,16 @@ enum tcpcheck_eval_ret tcpcheck_eval_connect(struct check *check, struct tcpchec
 #ifdef USE_OPENSSL
        if (conn_is_ssl(conn)) {
                if (connect->sni)
-                       ssl_sock_set_servername(conn, connect->sni);
+                       sni = ist(connect->sni);
                else if ((connect->options & TCPCHK_OPT_DEFAULT_CONNECT) && s && s->check.sni)
-                       ssl_sock_set_servername(conn, s->check.sni);
+                       sni = ist(s->check.sni);
                else if (auto_sni)
-                       ssl_sock_set_servername(conn, b_orig(auto_sni));
+                       sni = ist2(b_orig(auto_sni), b_data(auto_sni));
+
+               if (isttest(sni)) {
+                       conn->sni_hash = ssl_sock_sni_hash(sni);
+                       ssl_sock_set_servername(conn, istptr(sni));
+               }
 
                if (connect->alpn)
                        ssl_sock_set_alpn(conn, (unsigned char *)connect->alpn, connect->alpn_len);