]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: proxy_protocol: Ingest PP2_TYPE_UNIQUE_ID on incoming connections
authorTim Duesterhus <tim@bastelstu.be>
Fri, 13 Mar 2020 11:34:23 +0000 (12:34 +0100)
committerWilly Tarreau <w@1wt.eu>
Fri, 13 Mar 2020 16:25:23 +0000 (17:25 +0100)
This patch reads a proxy protocol v2 provided unique ID and makes it
available using the `fc_pp_unique_id` fetch.

doc/configuration.txt
include/proto/connection.h
include/types/connection.h
reg-tests/stream/unique-id-from-proxy.vtc [new file with mode: 0644]
src/connection.c

index 33425a6c6ee354eb0448a871d517744109da0241..57f777a78a46c5c6ad47627ce2319488a1a15024 100644 (file)
@@ -15131,6 +15131,10 @@ fc_pp_authority : string
   Returns the authority TLV sent by the client in the PROXY protocol header,
   if any.
 
+fc_pp_unique_id : string
+  Returns the unique ID TLV sent by the client in the PROXY protocol header,
+  if any.
+
 fc_rcvd_proxy : boolean
   Returns true if the client initiated the connection with a PROXY protocol
   header.
index fb264d2b59d60d797a65dce6069c95cbe835e386..9b8eb8ad3deb46e9d2b2abe7d83d698b07fcbb69 100644 (file)
@@ -325,6 +325,7 @@ static inline void conn_init(struct connection *conn)
        conn->src = NULL;
        conn->dst = NULL;
        conn->proxy_authority = NULL;
+       conn->proxy_unique_id = IST_NULL;
 }
 
 /* sets <owner> as the connection's owner */
@@ -458,6 +459,10 @@ static inline void conn_free(struct connection *conn)
                pool_free(pool_head_authority, conn->proxy_authority);
                conn->proxy_authority = NULL;
        }
+       if (isttest(conn->proxy_unique_id)) {
+               pool_free(pool_head_uniqueid, conn->proxy_unique_id.ptr);
+               conn->proxy_unique_id = IST_NULL;
+       }
 
        /* By convention we always place a NULL where the ctx points to if the
         * mux is null. It may have been used to store the connection as a
index 0c2d960b95cf950de615e6e84fa09069c6188010..30cb895ff977417726fb3c199fa188ed5aa031d2 100644 (file)
@@ -469,6 +469,7 @@ struct connection {
        char *proxy_authority;        /* Value of authority TLV received via PROXYv2 */
        unsigned int idle_time;                 /* Time the connection was added to the idle list, or 0 if not in the idle list */
        uint8_t proxy_authority_len;  /* Length of authority TLV received via PROXYv2 */
+       struct ist proxy_unique_id;  /* Value of the unique ID TLV received via PROXYv2 */
 };
 
 /* PROTO token registration */
diff --git a/reg-tests/stream/unique-id-from-proxy.vtc b/reg-tests/stream/unique-id-from-proxy.vtc
new file mode 100644 (file)
index 0000000..81ee3de
--- /dev/null
@@ -0,0 +1,38 @@
+varnishtest "Check that we are able to read a unique-id from PROXYv2"
+
+#REQUIRE_VERSION=2.2
+
+feature ignore_unknown_macro
+
+haproxy h1 -conf {
+    defaults
+        mode http
+        timeout connect 1s
+        timeout client  1s
+        timeout server  1s
+
+    frontend echo
+        bind "fd@${fe1}" accept-proxy
+        http-after-response set-header echo %[fc_pp_unique_id,hex]
+        http-request return status 200
+} -start
+
+client c1 -connect ${h1_fe1_sock} {
+    # PROXY v2 signature
+    sendhex "0d 0a 0d 0a 00 0d 0a 51 55 49 54 0a"
+    # version + PROXY
+    sendhex "21"
+    # TCP4
+    sendhex "11"
+    # length of the address (12) + length of the TLV (8)
+    sendhex "00 14"
+    # 127.0.0.1 42 127.0.0.1 1337
+    sendhex "7F 00 00 01 7F 00 00 01 00 2A 05 39"
+    # PP2_TYPE_UNIQUE_ID + length of the value + "12345"
+    sendhex "05 00 05 31 32 33 34 35"
+
+    txreq -url "/"
+    rxresp
+    expect resp.status == 200
+    expect resp.http.echo == "3132333435"
+} -run
index 4e3a92f0c94faf7675f3e54bfb68b41c23e33a70..728c0ec397cdd4169e5e40891dec223dec9468f8 100644 (file)
@@ -755,6 +755,22 @@ int conn_recv_proxy(struct connection *conn, int flag)
                                conn->proxy_authority_len = tlv_len;
                                break;
                        }
+                       case PP2_TYPE_UNIQUE_ID: {
+                               const struct ist tlv = ist2((const char *)tlv_packet->value, tlv_len);
+
+                               if (tlv.len > UNIQUEID_LEN)
+                                       goto bad_header;
+                               conn->proxy_unique_id.ptr = pool_alloc(pool_head_uniqueid);
+                               if (!isttest(conn->proxy_unique_id))
+                                       goto fail;
+                               if (istcpy(&conn->proxy_unique_id, tlv, UNIQUEID_LEN) < 0) {
+                                       /* This is technically unreachable, because we verified above
+                                        * that the TLV value fits.
+                                        */
+                                       goto fail;
+                               }
+                               break;
+                       }
                        default:
                                break;
                        }
@@ -1586,6 +1602,31 @@ int smp_fetch_fc_pp_authority(const struct arg *args, struct sample *smp, const
        return 1;
 }
 
+/* fetch the unique ID TLV from a PROXY protocol header */
+int smp_fetch_fc_pp_unique_id(const struct arg *args, struct sample *smp, const char *kw, void *private)
+{
+       struct connection *conn;
+
+       conn = objt_conn(smp->sess->origin);
+       if (!conn)
+               return 0;
+
+       if (conn->flags & CO_FL_WAIT_XPRT) {
+               smp->flags |= SMP_F_MAY_CHANGE;
+               return 0;
+       }
+
+       if (!isttest(conn->proxy_unique_id))
+               return 0;
+
+       smp->flags = 0;
+       smp->data.type = SMP_T_STR;
+       smp->data.u.str.area = conn->proxy_unique_id.ptr;
+       smp->data.u.str.data = conn->proxy_unique_id.len;
+
+       return 1;
+}
+
 /* Note: must not be declared <const> as its list will be overwritten.
  * Note: fetches that may return multiple types must be declared as the lowest
  * common denominator, the type that can be casted into all other ones. For
@@ -1596,6 +1637,7 @@ static struct sample_fetch_kw_list sample_fetch_keywords = {ILH, {
        { "bc_http_major", smp_fetch_fc_http_major, 0, NULL, SMP_T_SINT, SMP_USE_L4SRV },
        { "fc_rcvd_proxy", smp_fetch_fc_rcvd_proxy, 0, NULL, SMP_T_BOOL, SMP_USE_L4CLI },
        { "fc_pp_authority", smp_fetch_fc_pp_authority, 0, NULL, SMP_T_STR, SMP_USE_L4CLI },
+       { "fc_pp_unique_id", smp_fetch_fc_pp_unique_id, 0, NULL, SMP_T_STR, SMP_USE_L4CLI },
        { /* END */ },
 }};