]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: connection: use attach-srv name as SNI reuse parameter on reverse
authorAmaury Denoyelle <adenoyelle@haproxy.com>
Tue, 22 Aug 2023 14:58:55 +0000 (16:58 +0200)
committerAmaury Denoyelle <adenoyelle@haproxy.com>
Thu, 24 Aug 2023 15:02:34 +0000 (17:02 +0200)
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.

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

index 98a010e0355323d8d7b5a310298a1cfcdce9d851..cf4ec5a95dce43fe37d3a082a6de49daed150608 100644 (file)
@@ -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;
 };
 
index f6ac7dbf5030bd0f2554515a2ef864436f5db827..6363ff7fd488df8248e4a362ac38bfd4104a0c19 100644 (file)
@@ -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;
 }
 
index ab0649937dc6ea5885b340e79034a60c44bf7d9a..291f70488d26e6caa2d71e1c46067ce6c1a97043 100644 (file)
@@ -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;
 }