From d1b15b6e9b4d4d378a6169929a86f25b95eafc57 Mon Sep 17 00:00:00 2001 From: Tim Duesterhus Date: Fri, 13 Mar 2020 12:34:23 +0100 Subject: [PATCH] MINOR: proxy_protocol: Ingest PP2_TYPE_UNIQUE_ID on incoming connections This patch reads a proxy protocol v2 provided unique ID and makes it available using the `fc_pp_unique_id` fetch. --- doc/configuration.txt | 4 +++ include/proto/connection.h | 5 +++ include/types/connection.h | 1 + reg-tests/stream/unique-id-from-proxy.vtc | 38 ++++++++++++++++++++ src/connection.c | 42 +++++++++++++++++++++++ 5 files changed, 90 insertions(+) create mode 100644 reg-tests/stream/unique-id-from-proxy.vtc diff --git a/doc/configuration.txt b/doc/configuration.txt index 33425a6c6e..57f777a78a 100644 --- a/doc/configuration.txt +++ b/doc/configuration.txt @@ -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. diff --git a/include/proto/connection.h b/include/proto/connection.h index fb264d2b59..9b8eb8ad3d 100644 --- a/include/proto/connection.h +++ b/include/proto/connection.h @@ -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 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 diff --git a/include/types/connection.h b/include/types/connection.h index 0c2d960b95..30cb895ff9 100644 --- a/include/types/connection.h +++ b/include/types/connection.h @@ -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 index 0000000000..81ee3dea95 --- /dev/null +++ b/reg-tests/stream/unique-id-from-proxy.vtc @@ -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 diff --git a/src/connection.c b/src/connection.c index 4e3a92f0c9..728c0ec397 100644 --- a/src/connection.c +++ b/src/connection.c @@ -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 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 */ }, }}; -- 2.39.5