When accept-proxy or accept-netscaler-cip are being used, this gives the
ability to perform action based on the TCP connections between upstream
proxy and haproxy instead of the connection between the client and the
upstream proxy.
---
 doc/configuration.txt | 28 ++++++++++++++++
 src/proto_tcp.c       | 93 +++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 121 insertions(+)

diff --git a/doc/configuration.txt b/doc/configuration.txt
index ec851d80d66c..a8036abf9f22 100644
--- a/doc/configuration.txt
+++ b/doc/configuration.txt
@@ -13164,6 +13164,34 @@ fe_id : integer
   backends to check from which backend it was called, or to stick all users
   coming via a same frontend to the same server.
 
+proxy_dst : ip
+  This is the destination IP address of TCP connection from the upstream
+  proxy if "accept-proxy" or "accept-netscaler-cip" bind directive is used.
+
+proxy_dst_port : integer
+  Returns an integer value corresponding to the destination TCP port of the
+  upstream proxy if "accept-proxy" or "accept-netscaler-cip" bind directive is
+  used.
+
+proxy_src : ip
+  This is the source IP address of TCP connection from the upstream
+  proxy if "accept-proxy" or "accept-netscaler-cip" bind directive is used.
+  It is of type IP and works on both IPv4 and IPv6 tables. On IPv6 tables, IPv4
+  addresses are mapped to their IPv6 equivalent, according to RFC 4291. Note
+  that it is the TCP-level source address which is used, and not the address of
+  a client behind a proxy.
+
+  Example:
+       # Allow connection only from known upstream proxy
+       acl known-proxy proxy_src 198.51.100.29
+       http-request deny if !proxy_src
+
+proxy_src_port : integer
+  Returns an integer value corresponding to the TCP source port of the upstream
+  proxy if "accept-proxy" or "accept-netscaler-cip" bind directive is used.
+  Usage of this function is very limited as modern protocols do not care much
+  about source ports nowadays.
+
 sc_bytes_in_rate(<ctr>[,<table>]) : integer
 sc0_bytes_in_rate([<table>]) : integer
 sc1_bytes_in_rate([<table>]) : integer
diff --git a/src/proto_tcp.c b/src/proto_tcp.c
index 8b3d546fd1e8..dd3ec09abecf 100644
--- a/src/proto_tcp.c
+++ b/src/proto_tcp.c
@@ -2420,6 +2420,31 @@ int smp_fetch_src(const struct arg *args, struct sample 
*smp, const char *kw, vo
        return 1;
 }
 
+/* fetch the connection's proxy source IPv4/IPv6 address */
+int smp_fetch_proxy_src(const struct arg *args, struct sample *smp, const char 
*kw, void *private)
+{
+       struct connection *cli_conn = objt_conn(smp->sess->origin);
+
+       if (!cli_conn)
+               return 0;
+
+       switch (cli_conn->proxy_addr.from.ss_family) {
+       case AF_INET:
+               smp->data.u.ipv4 = ((struct sockaddr_in 
*)&cli_conn->proxy_addr.from)->sin_addr;
+               smp->data.type = SMP_T_IPV4;
+               break;
+       case AF_INET6:
+               smp->data.u.ipv6 = ((struct sockaddr_in6 
*)&cli_conn->proxy_addr.from)->sin6_addr;
+               smp->data.type = SMP_T_IPV6;
+               break;
+       default:
+               return 0;
+       }
+
+       smp->flags = 0;
+       return 1;
+}
+
 /* set temp integer to the connection's source port */
 static int
 smp_fetch_sport(const struct arg *args, struct sample *smp, const char *k, 
void *private)
@@ -2437,6 +2462,23 @@ smp_fetch_sport(const struct arg *args, struct sample 
*smp, const char *k, void
        return 1;
 }
 
+/* fetch the connection's proxy source TCP port */
+static int
+smp_fetch_proxy_sport(const struct arg *args, struct sample *smp, const char 
*k, void *private)
+{
+       struct connection *cli_conn = objt_conn(smp->sess->origin);
+
+       if (!cli_conn)
+               return 0;
+
+       smp->data.type = SMP_T_SINT;
+       if (!(smp->data.u.sint = get_host_port(&cli_conn->proxy_addr.from)))
+               return 0;
+
+       smp->flags = 0;
+       return 1;
+}
+
 /* fetch the connection's destination IPv4/IPv6 address */
 static int
 smp_fetch_dst(const struct arg *args, struct sample *smp, const char *kw, void 
*private)
@@ -2465,6 +2507,34 @@ smp_fetch_dst(const struct arg *args, struct sample 
*smp, const char *kw, void *
        return 1;
 }
 
+/* fetch the connection's proxy destination IPv4/IPv6 address */
+static int
+smp_fetch_proxy_dst(const struct arg *args, struct sample *smp, const char 
*kw, void *private)
+{
+       struct connection *cli_conn = objt_conn(smp->sess->origin);
+
+       if (!cli_conn)
+               return 0;
+
+       conn_get_to_proxy_addr(cli_conn);
+
+       switch (cli_conn->proxy_addr.to.ss_family) {
+       case AF_INET:
+               smp->data.u.ipv4 = ((struct sockaddr_in 
*)&cli_conn->proxy_addr.to)->sin_addr;
+               smp->data.type = SMP_T_IPV4;
+               break;
+       case AF_INET6:
+               smp->data.u.ipv6 = ((struct sockaddr_in6 
*)&cli_conn->proxy_addr.to)->sin6_addr;
+               smp->data.type = SMP_T_IPV6;
+               break;
+       default:
+               return 0;
+       }
+
+       smp->flags = 0;
+       return 1;
+}
+
 /* check if the destination address of the front connection is local to the
  * system or if it was intercepted.
  */
@@ -2526,6 +2596,25 @@ smp_fetch_dport(const struct arg *args, struct sample 
*smp, const char *kw, void
        return 1;
 }
 
+/* fetch the connection's proxy destination TCP port */
+static int
+smp_fetch_proxy_dport(const struct arg *args, struct sample *smp, const char 
*kw, void *private)
+{
+       struct connection *cli_conn = objt_conn(smp->sess->origin);
+
+       if (!cli_conn)
+               return 0;
+
+       conn_get_to_proxy_addr(cli_conn);
+
+       smp->data.type = SMP_T_SINT;
+       if (!(smp->data.u.sint = get_host_port(&cli_conn->proxy_addr.to)))
+               return 0;
+
+       smp->flags = 0;
+       return 1;
+}
+
 #ifdef TCP_INFO
 
 /* Returns some tcp_info data is its avalaible. "dir" must be set to 0 if
@@ -2907,6 +2996,10 @@ static struct sample_fetch_kw_list sample_fetch_keywords 
= {ILH, {
        { "src",      smp_fetch_src,   0, NULL, SMP_T_IPV4, SMP_USE_L4CLI },
        { "src_is_local", smp_fetch_src_is_local, 0, NULL, SMP_T_BOOL, 
SMP_USE_L4CLI },
        { "src_port", smp_fetch_sport, 0, NULL, SMP_T_SINT, SMP_USE_L4CLI },
+       { "proxy_dst",      smp_fetch_proxy_dst,   0, NULL, SMP_T_IPV4, 
SMP_USE_L4CLI },
+       { "proxy_dst_port", smp_fetch_proxy_dport, 0, NULL, SMP_T_SINT, 
SMP_USE_L4CLI },
+       { "proxy_src",      smp_fetch_proxy_src,   0, NULL, SMP_T_IPV4, 
SMP_USE_L4CLI },
+       { "proxy_src_port", smp_fetch_proxy_sport, 0, NULL, SMP_T_SINT, 
SMP_USE_L4CLI },
 #ifdef TCP_INFO
        { "fc_rtt",           smp_fetch_fc_rtt,           ARG1(0,STR), NULL, 
SMP_T_SINT, SMP_USE_L4CLI },
        { "fc_rttvar",        smp_fetch_fc_rttvar,        ARG1(0,STR), NULL, 
SMP_T_SINT, SMP_USE_L4CLI },

Reply via email to