mirror of
http://git.haproxy.org/git/haproxy.git/
synced 2024-12-16 16:34:42 +00:00
MINOR: connection: add the fc_pp_authority fetch -- authority TLV, from PROXYv2
Save the authority TLV in a PROXYv2 header from the client connection, if present, and make it available as fc_pp_authority. The fetch can be used, for example, to set the SNI for a backend TLS connection.
This commit is contained in:
parent
c326ecc9b1
commit
7185b789f9
@ -14467,6 +14467,10 @@ fc_http_major : integer
|
||||
for HTTP/0.9 to HTTP/1.1 or 2 for HTTP/2. Note, this is based on the on-wire
|
||||
encoding and not on the version present in the request header.
|
||||
|
||||
fc_pp_authority : string
|
||||
Returns the authority 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.
|
||||
|
@ -35,6 +35,7 @@
|
||||
extern struct pool_head *pool_head_connection;
|
||||
extern struct pool_head *pool_head_connstream;
|
||||
extern struct pool_head *pool_head_sockaddr;
|
||||
extern struct pool_head *pool_head_authority;
|
||||
extern struct xprt_ops *registered_xprt[XPRT_ENTRIES];
|
||||
extern struct mux_proto_list mux_proto_list;
|
||||
|
||||
@ -471,6 +472,7 @@ static inline void conn_init(struct connection *conn)
|
||||
conn->idle_time = 0;
|
||||
conn->src = NULL;
|
||||
conn->dst = NULL;
|
||||
conn->proxy_authority = NULL;
|
||||
}
|
||||
|
||||
/* sets <owner> as the connection's owner */
|
||||
@ -617,6 +619,11 @@ static inline void conn_free(struct connection *conn)
|
||||
sockaddr_free(&conn->src);
|
||||
sockaddr_free(&conn->dst);
|
||||
|
||||
if (conn->proxy_authority != NULL) {
|
||||
pool_free(pool_head_authority, conn->proxy_authority);
|
||||
conn->proxy_authority = 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
|
||||
* stream_interface's end point for example.
|
||||
|
@ -461,7 +461,9 @@ struct connection {
|
||||
void (*destroy_cb)(struct connection *conn); /* callback to notify of imminent death of the connection */
|
||||
struct sockaddr_storage *src; /* source address (pool), when known, otherwise NULL */
|
||||
struct sockaddr_storage *dst; /* destination address (pool), when known, otherwise NULL */
|
||||
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 */
|
||||
};
|
||||
|
||||
/* PROTO token registration */
|
||||
@ -578,6 +580,8 @@ struct tlv_ssl {
|
||||
#define PP2_CLIENT_CERT_CONN 0x02
|
||||
#define PP2_CLIENT_CERT_SESS 0x04
|
||||
|
||||
/* Max length of the authority TLV */
|
||||
#define PP2_AUTHORITY_MAX 255
|
||||
|
||||
/*
|
||||
* Linux seems to be able to send 253 fds per sendmsg(), not sure
|
||||
|
@ -32,6 +32,7 @@
|
||||
DECLARE_POOL(pool_head_connection, "connection", sizeof(struct connection));
|
||||
DECLARE_POOL(pool_head_connstream, "conn_stream", sizeof(struct conn_stream));
|
||||
DECLARE_POOL(pool_head_sockaddr, "sockaddr", sizeof(struct sockaddr_storage));
|
||||
DECLARE_POOL(pool_head_authority, "authority", PP2_AUTHORITY_MAX);
|
||||
|
||||
struct xprt_ops *registered_xprt[XPRT_ENTRIES] = { NULL, };
|
||||
|
||||
@ -631,6 +632,16 @@ int conn_recv_proxy(struct connection *conn, int flag)
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
case PP2_TYPE_AUTHORITY: {
|
||||
if (tlv_len > PP2_AUTHORITY_MAX)
|
||||
goto bad_header;
|
||||
conn->proxy_authority = pool_alloc(pool_head_authority);
|
||||
if (conn->proxy_authority == NULL)
|
||||
goto fail;
|
||||
memcpy(conn->proxy_authority, (const char *)tlv_packet->value, tlv_len);
|
||||
conn->proxy_authority_len = tlv_len;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -1415,6 +1426,31 @@ int smp_fetch_fc_rcvd_proxy(const struct arg *args, struct sample *smp, const ch
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* fetch the authority TLV from a PROXY protocol header */
|
||||
int smp_fetch_fc_pp_authority(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_CONNECTED)) {
|
||||
smp->flags |= SMP_F_MAY_CHANGE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (conn->proxy_authority == NULL)
|
||||
return 0;
|
||||
|
||||
smp->flags = 0;
|
||||
smp->data.type = SMP_T_STR;
|
||||
smp->data.u.str.area = conn->proxy_authority;
|
||||
smp->data.u.str.data = conn->proxy_authority_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
|
||||
@ -1424,6 +1460,7 @@ static struct sample_fetch_kw_list sample_fetch_keywords = {ILH, {
|
||||
{ "fc_http_major", smp_fetch_fc_http_major, 0, NULL, SMP_T_SINT, SMP_USE_L4CLI },
|
||||
{ "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 },
|
||||
{ /* END */ },
|
||||
}};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user