diff --git a/doc/configuration.txt b/doc/configuration.txt index a04c6f763..13e136d57 100644 --- a/doc/configuration.txt +++ b/doc/configuration.txt @@ -6418,7 +6418,7 @@ tcp-request connection [{if | unless} ] Arguments : defines the action to perform if the condition applies. Valid actions include : "accept", "reject", "track-sc1", "track-sc2", - and "track-sc3". See below for more details. + "track-sc3", and "expect-proxy". See below for more details. is a standard layer4-only ACL-based condition (see section 7). @@ -6456,6 +6456,15 @@ tcp-request connection [{if | unless} ] logging is absolutely desired, then "tcp-request content" rules should be used instead. + - expect-proxy layer4 : + configures the client-facing connection to receive a PROXY protocol + header before any byte is read from the socket. This is equivalent to + having the "accept-proxy" keyword on the "bind" line, except that using + the TCP rule allows the PROXY protocol to be accepted only for certain + IP address ranges using an ACL. This is convenient when multiple layers + of load balancers are passed through by traffic coming from public + hosts. + - { track-sc1 | track-sc2 | track-sc3 } [table ] : enables tracking of sticky counters from current connection. These rules do not stop evaluation and do not change default action. Two sets @@ -6516,6 +6525,10 @@ tcp-request connection [{if | unless} ] tcp-request connection track-sc1 src tcp-request connection reject if { sc1_conn_rate gt 10 } + Example: enable the PROXY protocol for traffic coming from all known proxies. + + tcp-request connection expect-proxy layer4 if { src -f proxies.lst } + See section 7 about ACL usage. See also : "tcp-request content", "stick-table" @@ -7267,7 +7280,8 @@ accept-proxy address will still be used. This keyword combined with support from external components can be used as an efficient and reliable alternative to the X-Forwarded-For mechanism which is not always reliable and not even always - usable. + usable. See also "tcp-request connection expect-proxy" for a finer-grained + setting of which client is allowed to use the protocol. alpn This enables the TLS ALPN extension and advertises the specified protocol diff --git a/include/types/proto_tcp.h b/include/types/proto_tcp.h index ac9d328b5..c9fd1e4a6 100644 --- a/include/types/proto_tcp.h +++ b/include/types/proto_tcp.h @@ -32,9 +32,10 @@ enum { TCP_ACT_ACCEPT = 1, TCP_ACT_REJECT = 2, - TCP_ACT_TRK_SC1 = 3, /* TCP request tracking : must be contiguous */ - TCP_ACT_TRK_SC2 = 4, - TCP_ACT_TRK_SC3 = 5, + TCP_ACT_EXPECT_PX = 3, + TCP_ACT_TRK_SC1 = 4, /* TCP request tracking : must be contiguous */ + TCP_ACT_TRK_SC2 = 5, + TCP_ACT_TRK_SC3 = 6, }; struct tcp_rule { diff --git a/src/proto_tcp.c b/src/proto_tcp.c index 049988c4e..956f803b5 100644 --- a/src/proto_tcp.c +++ b/src/proto_tcp.c @@ -1105,6 +1105,10 @@ int tcp_exec_req_rules(struct session *s) if (key && (ts = stktable_get_entry(t, key))) session_track_stkctr(&s->stkctr[tcp_trk_idx(rule->action)], t, ts); } + else if (rule->action == TCP_ACT_EXPECT_PX) { + s->si[0].conn->flags |= CO_FL_ACCEPT_PROXY; + conn_sock_want_recv(s->si[0].conn); + } else { /* otherwise it's an accept */ break; @@ -1222,6 +1226,24 @@ static int tcp_parse_request_rule(char **args, int arg, int section_type, rule->act_prm.trk_ctr.expr = expr; rule->action = TCP_ACT_TRK_SC1 + args[kw][8] - '1'; } + else if (strcmp(args[arg], "expect-proxy") == 0) { + if (strcmp(args[arg+1], "layer4") != 0) { + memprintf(err, + "'%s %s %s' only supports 'layer4' in %s '%s' (got '%s')", + args[0], args[1], args[arg], proxy_type_str(curpx), curpx->id, args[arg+1]); + return -1; + } + + if (!(where & SMP_VAL_FE_CON_ACC)) { + memprintf(err, + "'%s %s' is not allowed in '%s %s' rules in %s '%s'", + args[arg], args[arg+1], args[0], args[1], proxy_type_str(curpx), curpx->id); + return -1; + } + + arg += 2; + rule->action = TCP_ACT_EXPECT_PX; + } else { memprintf(err, "'%s %s' expects 'accept', 'reject', 'track-sc1', 'track-sc2' "