]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: connection: use sni as parameter for srv conn hash
authorAmaury Denoyelle <adenoyelle@haproxy.com>
Wed, 6 Jan 2021 16:03:27 +0000 (17:03 +0100)
committerAmaury Denoyelle <adenoyelle@haproxy.com>
Fri, 12 Feb 2021 11:48:11 +0000 (12:48 +0100)
The sni parameter is an input to the server connection hash. Do not add
anymore connections with dynamic sni in the private list. Thus, it is
now possible to reuse a server connection if they use the same sni.

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

index a8239b43fe0c2faa57d1f9b6a7c8e75385fdb125..9ee00819bfaef0dc18c44a1db04a831b4944ebe7 100644 (file)
@@ -33,6 +33,7 @@
 #include <import/xxhash.h>
 
 #include <haproxy/api-t.h>
+#include <haproxy/buf-t.h>
 #include <haproxy/listener-t.h>
 #include <haproxy/obj_type-t.h>
 #include <haproxy/port_range-t.h>
@@ -471,8 +472,7 @@ struct conn_stream {
  * CAUTION! Always update CONN_HASH_PARAMS_TYPE_COUNT when adding a new entry.
  */
 enum conn_hash_params_t {
-       /* to remove as soon as one useful parameter is present */
-       CONN_HASH_DUMMY_PARAM,
+       CONN_HASH_PARAMS_TYPE_SNI = 0x1,
 };
 #define CONN_HASH_PARAMS_TYPE_COUNT 1
 
@@ -488,6 +488,7 @@ enum conn_hash_params_t {
  */
 struct conn_hash_params {
        struct server *srv;
+       XXH64_hash_t *sni_prehash;
 };
 
 /* This structure describes a connection with its methods and data.
index fed177c9bd4ead508b84f915fa711401b59925d9..d9d5c97e19d0c874e382b7f388038ac467c0bd69 100644 (file)
@@ -1246,8 +1246,10 @@ int connect_server(struct stream *s)
        int reuse = 0;
        int init_mux = 0;
        int err;
+       struct sample *sni_smp = NULL;
        int64_t hash = 0;
        struct conn_hash_params hash_params;
+       XXH64_hash_t sni_hash;
 
        /* first, set unique connection parameters and then calculate hash */
        memset(&hash_params, 0, sizeof(hash_params));
@@ -1255,6 +1257,20 @@ int connect_server(struct stream *s)
        srv = objt_server(s->target);
        hash_params.srv = srv;
 
+#ifdef USE_OPENSSL
+       /* 1. sni */
+       if (srv && 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_hash = conn_hash_prehash(sni_smp->data.u.str.area,
+                                                    sni_smp->data.u.str.data);
+                       hash_params.sni_prehash = &sni_hash;
+               }
+       }
+#endif /* USE_OPENSSL */
+
        if (srv)
                hash = conn_calculate_hash(&hash_params);
 
@@ -1547,19 +1563,8 @@ skip_reuse:
                return err;
 
 #ifdef USE_OPENSSL
-       if (srv && srv->ssl_ctx.sni) {
-               struct sample *smp;
-
-               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(smp)) {
-                       ssl_sock_set_servername(srv_conn, smp->data.u.str.area);
-                       if (!(srv->ssl_ctx.sni->fetch->use & SMP_USE_INTRN) ||
-                           smp->flags & SMP_F_VOLATILE) {
-                               conn_set_private(srv_conn);
-                       }
-               }
-       }
+       if (smp_make_safe(sni_smp))
+               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,
index 3656b36366f08c735a7d588ae6c220efee5599f6..6126dd180348df8ebbeee18d427c66440ecb7dde 100644 (file)
@@ -1423,6 +1423,12 @@ XXH64_hash_t conn_calculate_hash(const struct conn_hash_params *params)
 
        conn_hash_update(buf, &idx, &params->srv, sizeof(params->srv), &hash_flags, 0);
 
+       if (params->sni_prehash) {
+               conn_hash_update(buf, &idx,
+                                params->sni_prehash, sizeof(*params->sni_prehash),
+                                &hash_flags, CONN_HASH_PARAMS_TYPE_SNI);
+       }
+
        hash = conn_hash_digest(buf, idx, hash_flags);
        return hash;
 }