From: Willy Tarreau Date: Tue, 11 Jun 2013 18:40:55 +0000 (+0200) Subject: MEDIUM: tcp: add "tcp-request connection expect-proxy layer4" X-Git-Tag: v1.5-dev19~13 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=4f0d919bd4951d2f22f2334f694a39d5d940aa10;p=thirdparty%2Fhaproxy.git MEDIUM: tcp: add "tcp-request connection expect-proxy layer4" This 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. --- diff --git a/doc/configuration.txt b/doc/configuration.txt index a04c6f763b..13e136d570 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 ac9d328b58..c9fd1e4a6b 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 049988c4e1..956f803b51 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' "