From: Amaury Denoyelle Date: Tue, 22 Aug 2023 14:58:55 +0000 (+0200) Subject: MINOR: connection: use attach-srv name as SNI reuse parameter on reverse X-Git-Tag: v2.9-dev4~26 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=1723e21af21e9f1f53f890b4fe999f1e83b3d448;p=thirdparty%2Fhaproxy.git MINOR: connection: use attach-srv name as SNI reuse parameter on reverse On connection passive reverse from frontend to backend, its hash node is calculated to be able to select it from the idle server pool. If attach-srv rule defined an associated name, reuse it as the value for SNI prehash. This change allows a client to select a reverse connection by its name by configuring its server line with a SNI to permit this. --- diff --git a/include/haproxy/connection-t.h b/include/haproxy/connection-t.h index 98a010e035..cf4ec5a95d 100644 --- a/include/haproxy/connection-t.h +++ b/include/haproxy/connection-t.h @@ -546,7 +546,8 @@ struct connection { /* Members used if connection must be reversed. */ struct { - enum obj_type *target; /* Server for passive reverse. */ + enum obj_type *target; /* Listener for active reverse, server for passive. */ + struct buffer name; /* Only used for passive reverse. Used as SNI when connection added to server idle pool. */ } reverse; }; diff --git a/src/connection.c b/src/connection.c index f6ac7dbf50..6363ff7fd4 100644 --- a/src/connection.c +++ b/src/connection.c @@ -436,6 +436,7 @@ void conn_init(struct connection *conn, void *target) conn->hash_node = NULL; conn->xprt = NULL; conn->reverse.target = NULL; + conn->reverse.name = BUF_NULL; } /* Initialize members used for backend connections. @@ -531,6 +532,8 @@ void conn_free(struct connection *conn) pool_free(pool_head_uniqueid, istptr(conn->proxy_unique_id)); conn->proxy_unique_id = IST_NULL; + ha_free(&conn->reverse.name.area); + conn_force_unsubscribe(conn); pool_free(pool_head_connection, conn); } @@ -2461,6 +2464,15 @@ int conn_reverse(struct connection *conn) memset(&hash_params, 0, sizeof(hash_params)); hash_params.target = srv; + if (b_data(&conn->reverse.name)) { + /* 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 = + conn_hash_prehash(b_head(&conn->reverse.name), + b_data(&conn->reverse.name)); + } + hash = conn_calculate_hash(&hash_params); conn->hash_node->node.key = hash; @@ -2481,6 +2493,9 @@ int conn_reverse(struct connection *conn) SWAP(conn->src, conn->dst); conn->reverse.target = NULL; + ha_free(&conn->reverse.name.area); + conn->reverse.name = BUF_NULL; + return 0; } diff --git a/src/tcp_act.c b/src/tcp_act.c index ab0649937d..291f70488d 100644 --- a/src/tcp_act.c +++ b/src/tcp_act.c @@ -44,11 +44,30 @@ static enum act_return tcp_action_attach_srv(struct act_rule *rule, struct proxy struct session *sess, struct stream *s, int flags) { struct server *srv = rule->arg.attach_srv.srv; + struct sample *name_smp; struct connection *conn = objt_conn(sess->origin); if (!conn) return ACT_RET_ABRT; conn_set_reverse(conn, &srv->obj_type); + + if (rule->arg.attach_srv.name) { + name_smp = sample_fetch_as_type(sess->fe, sess, s, + SMP_OPT_DIR_REQ | SMP_OPT_FINAL, + rule->arg.attach_srv.name, SMP_T_STR); + /* TODO strdup du buffer du sample */ + if (name_smp) { + struct buffer *buf = &name_smp->data.u.str; + char *area = malloc(b_data(buf)); + + if (!area) + return ACT_RET_ERR; + + conn->reverse.name = b_make(area, b_data(buf), 0, 0); + b_ncat(&conn->reverse.name, buf, b_data(buf)); + } + } + return ACT_RET_CONT; }