From 47168e217a3af5f51abe6b1dabaed54274f0790b Mon Sep 17 00:00:00 2001 From: Amaury Denoyelle Date: Thu, 23 May 2024 18:31:48 +0200 Subject: [PATCH] MEDIUM: connection: use pool-conn-name instead of sni on reuse Implement pool-conn-name support for idle connection reuse. It replaces SNI as arbitrary identifier for connections in the idle pool. Thus, every SNI reference in this context have been replaced. Main change occurs in connect_server() where pool-conn-name sample fetch is now prehash to generate idle connection identifier. SNI is now solely used in the context of SSL for ssl_sock_set_servername(). --- include/haproxy/connection-t.h | 4 ++-- include/haproxy/connection.h | 2 +- src/backend.c | 37 ++++++++++++++++------------------ src/connection.c | 10 ++++----- 4 files changed, 25 insertions(+), 28 deletions(-) diff --git a/include/haproxy/connection-t.h b/include/haproxy/connection-t.h index 6ee0940be4..83969da06e 100644 --- a/include/haproxy/connection-t.h +++ b/include/haproxy/connection-t.h @@ -473,7 +473,7 @@ struct conn_src { * CAUTION! Always update CONN_HASH_PARAMS_TYPE_COUNT when adding a new entry. */ enum conn_hash_params_t { - CONN_HASH_PARAMS_TYPE_SNI = 0x1, + CONN_HASH_PARAMS_TYPE_NAME = 0x1, CONN_HASH_PARAMS_TYPE_DST_ADDR = 0x2, CONN_HASH_PARAMS_TYPE_DST_PORT = 0x4, CONN_HASH_PARAMS_TYPE_SRC_ADDR = 0x8, @@ -494,7 +494,7 @@ enum conn_hash_params_t { * connection hash. */ struct conn_hash_params { - uint64_t sni_prehash; + uint64_t name_prehash; uint64_t proxy_prehash; uint64_t mark_tos_prehash; void *target; diff --git a/include/haproxy/connection.h b/include/haproxy/connection.h index 91ddcd6a53..aa61cc71af 100644 --- a/include/haproxy/connection.h +++ b/include/haproxy/connection.h @@ -97,7 +97,7 @@ void sockaddr_free(struct sockaddr_storage **sap); /* connection hash stuff */ uint64_t conn_calculate_hash(const struct conn_hash_params *params); -uint64_t conn_hash_prehash(char *buf, size_t size); +uint64_t conn_hash_prehash(const char *buf, size_t size); int conn_reverse(struct connection *conn); diff --git a/src/backend.c b/src/backend.c index e5444988c2..d74ae40825 100644 --- a/src/backend.c +++ b/src/backend.c @@ -1349,9 +1349,7 @@ int connect_server(struct stream *s) int reuse = 0; int init_mux = 0; int err; -#ifdef USE_OPENSSL - struct sample *sni_smp = NULL; -#endif + struct sample *name_smp = NULL; struct sockaddr_storage *bind_addr = NULL; int proxy_line_ret; int64_t hash = 0; @@ -1373,13 +1371,11 @@ int connect_server(struct stream *s) if (err != SRV_STATUS_OK) return SF_ERR_INTERNAL; -#ifdef USE_OPENSSL - 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 (srv && srv->pool_conn_name_expr) { + name_smp = sample_fetch_as_type(s->be, s->sess, s, + SMP_OPT_DIR_REQ | SMP_OPT_FINAL, + srv->pool_conn_name_expr, SMP_T_STR); } -#endif /* do not reuse if mode is not http */ if (!IS_HTX_STRM(s)) { @@ -1403,17 +1399,12 @@ int connect_server(struct stream *s) /* 1. target */ hash_params.target = s->target; -#ifdef USE_OPENSSL - /* 2. sni - * only test if the sample is not null as smp_make_safe (called before - * ssl_sock_set_servername) can only fails if this is not the case - */ - if (sni_smp) { - hash_params.sni_prehash = - conn_hash_prehash(sni_smp->data.u.str.area, - sni_smp->data.u.str.data); + /* 2. pool-conn-name */ + if (name_smp) { + hash_params.name_prehash = + conn_hash_prehash(name_smp->data.u.str.area, + name_smp->data.u.str.data); } -#endif /* USE_OPENSSL */ /* 3. destination address */ if (srv && srv_is_transparent(srv)) @@ -1787,7 +1778,13 @@ int connect_server(struct stream *s) return err; #ifdef USE_OPENSSL - if (!(s->flags & SF_SRV_REUSED)) { + /* Set socket SNI unless connection is reused. */ + if (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); } diff --git a/src/connection.c b/src/connection.c index 97af8f65e5..d186c2f01e 100644 --- a/src/connection.c +++ b/src/connection.c @@ -2621,7 +2621,7 @@ INITCALL1(STG_REGISTER, cfg_register_keywords, &cfg_kws); /* Generate the hash of a connection with params as input * Each non-null field of params is taken into account for the hash calcul. */ -uint64_t conn_hash_prehash(char *buf, size_t size) +uint64_t conn_hash_prehash(const char *buf, size_t size) { return XXH64(buf, size, 0); } @@ -2699,10 +2699,10 @@ uint64_t conn_calculate_hash(const struct conn_hash_params *params) conn_hash_update(&hash, ¶ms->target, sizeof(params->target), &hash_flags, 0); - if (params->sni_prehash) { + if (params->name_prehash) { conn_hash_update(&hash, - ¶ms->sni_prehash, sizeof(params->sni_prehash), - &hash_flags, CONN_HASH_PARAMS_TYPE_SNI); + ¶ms->name_prehash, sizeof(params->name_prehash), + &hash_flags, CONN_HASH_PARAMS_TYPE_NAME); } if (params->dst_addr) { @@ -2770,7 +2770,7 @@ int conn_reverse(struct connection *conn) /* data cannot wrap else prehash usage is incorrect */ BUG_ON(b_data(&conn->reverse.name) != b_contig_data(&conn->reverse.name, 0)); - hash_params.sni_prehash = + hash_params.name_prehash = conn_hash_prehash(b_head(&conn->reverse.name), b_data(&conn->reverse.name)); }