]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MEDIUM: tcp: add "tcp-request connection expect-proxy layer4"
authorWilly Tarreau <w@1wt.eu>
Tue, 11 Jun 2013 18:40:55 +0000 (20:40 +0200)
committerWilly Tarreau <w@1wt.eu>
Tue, 11 Jun 2013 18:40:55 +0000 (20:40 +0200)
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.

doc/configuration.txt
include/types/proto_tcp.h
src/proto_tcp.c

index a04c6f763b6815ddacc4665cb7b587c1c8cd4a20..13e136d570059072db5b77b69796bd17c4527950 100644 (file)
@@ -6418,7 +6418,7 @@ tcp-request connection <action> [{if | unless} <condition>]
   Arguments :
     <action>    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.
 
     <condition> is a standard layer4-only ACL-based condition (see section 7).
 
@@ -6456,6 +6456,15 @@ tcp-request connection <action> [{if | unless} <condition>]
         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 } <key> [table <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 <action> [{if | unless} <condition>]
         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 <protocols>
   This enables the TLS ALPN extension and advertises the specified protocol
index ac9d328b58d7e2f1f7792110559aed530520ae85..c9fd1e4a6bf51e1e93bb45905076aaa866442d60 100644 (file)
 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 {
index 049988c4e1a2d8386dabcabc1b51cfb16922c837..956f803b5183778021efb94184464c9c228ce04e 100644 (file)
@@ -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' "