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.
This commit is contained in:
Tim Duesterhus 2020-03-13 12:34:23 +01:00 committed by Willy Tarreau
parent b435f77620
commit d1b15b6e9b
5 changed files with 90 additions and 0 deletions

View File

@ -15131,6 +15131,10 @@ fc_pp_authority : string
Returns the authority TLV sent by the client in the PROXY protocol header, Returns the authority TLV sent by the client in the PROXY protocol header,
if any. 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 fc_rcvd_proxy : boolean
Returns true if the client initiated the connection with a PROXY protocol Returns true if the client initiated the connection with a PROXY protocol
header. header.

View File

@ -325,6 +325,7 @@ static inline void conn_init(struct connection *conn)
conn->src = NULL; conn->src = NULL;
conn->dst = NULL; conn->dst = NULL;
conn->proxy_authority = NULL; conn->proxy_authority = NULL;
conn->proxy_unique_id = IST_NULL;
} }
/* sets <owner> as the connection's owner */ /* 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); pool_free(pool_head_authority, conn->proxy_authority);
conn->proxy_authority = NULL; 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 /* 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 * mux is null. It may have been used to store the connection as a

View File

@ -469,6 +469,7 @@ struct connection {
char *proxy_authority; /* Value of authority TLV received via PROXYv2 */ 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 */ 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 */ 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 */ /* PROTO token registration */

View File

@ -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

View File

@ -755,6 +755,22 @@ int conn_recv_proxy(struct connection *conn, int flag)
conn->proxy_authority_len = tlv_len; conn->proxy_authority_len = tlv_len;
break; 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: default:
break; break;
} }
@ -1586,6 +1602,31 @@ int smp_fetch_fc_pp_authority(const struct arg *args, struct sample *smp, const
return 1; 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: must not be declared <const> as its list will be overwritten.
* Note: fetches that may return multiple types must be declared as the lowest * 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 * 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 }, { "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_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_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 */ }, { /* END */ },
}}; }};