]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: tcp-sample: Add samples to get original info about client connection
authorChristopher Faulet <cfaulet@haproxy.com>
Mon, 25 Oct 2021 14:58:50 +0000 (16:58 +0200)
committerChristopher Faulet <cfaulet@haproxy.com>
Wed, 27 Oct 2021 09:35:59 +0000 (11:35 +0200)
Because source and destination address of the client connection are now
updated at the appropriated level (connection, session or stream), original
info about the client connection are preserved.  src/src_port/src_is_local
and dst/dst_port/dst_is_local return current info about the client
connection. It is the info at the highest available level. Most of time, the
stream. Any tcp/http rules may alter this info.

To get original info, "fc_" prefix must be added. For instance
"fc_src". Here, only "tcp-request connection" rules may alter source and
destination address/port.

doc/configuration.txt
src/tcp_sample.c

index b9d520fe23582e20791e0d98edd3c202b85feaa5..d90c39e66aad56412f33c33b94f07eef9b682676 100644 (file)
@@ -17995,16 +17995,17 @@ cur_tunnel_timeout : integer
   "set-timeout" rule has been applied. See also "be_tunnel_timeout".
 
 dst : ip
-  This is the destination IPv4 address of the connection on the client side,
-  which is the address the client connected to. It can be useful when running
-  in transparent mode. It is of type IP and works on both IPv4 and IPv6 tables.
-  On IPv6 tables, IPv4 address is mapped to its IPv6 equivalent, according to
-  RFC 4291. When the incoming connection passed through address translation or
-  redirection involving connection tracking, the original destination address
-  before the redirection will be reported. On Linux systems, the source and
-  destination may seldom appear reversed if the nf_conntrack_tcp_loose sysctl
-  is set, because a late response may reopen a timed out connection and switch
-  what is believed to be the source and the destination.
+  This is the destination IP address of the connection on the client side,
+  which is the address the client connected to. Any tcp/http rules may alter
+  this address. It can be useful when running in transparent mode. It is of
+  type IP and works on both IPv4 and IPv6 tables.  On IPv6 tables, IPv4 address
+  is mapped to its IPv6 equivalent, according to RFC 4291. When the incoming
+  connection passed through address translation or redirection involving
+  connection tracking, the original destination address before the redirection
+  will be reported. On Linux systems, the source and destination may seldom
+  appear reversed if the nf_conntrack_tcp_loose sysctl is set, because a late
+  response may reopen a timed out connection and switch what is believed to be
+  the source and the destination.
 
 dst_conn : integer
   Returns an integer value corresponding to the number of currently established
@@ -18029,10 +18030,10 @@ dst_is_local : boolean
 dst_port : integer
   Returns an integer value corresponding to the destination TCP port of the
   connection on the client side, which is the port the client connected to.
-  This might be used when running in transparent mode, when assigning dynamic
-  ports to some clients for a whole application session, to stick all users to
-  a same server, or to pass the destination port information to a server using
-  an HTTP header.
+  Any tcp/http rules may alter this address. This might be used when running in
+  transparent mode, when assigning dynamic ports to some clients for a whole
+  application session, to stick all users to a same server, or to pass the
+  destination port information to a server using an HTTP header.
 
 fc_conn_err : integer
   Returns the ID of the error that might have occurred on the current
@@ -18096,6 +18097,21 @@ fc_conn_err_str : string
   | 43 | "SSL fatal error"                                                         |
   +----+---------------------------------------------------------------------------+
 
+fc_dst : ip
+  This is the original destination IP address of the connection on the client
+  side. Only "tcp-request connection" rules may alter this address. See "dst"
+  for details.
+
+fc_dst_is_local : boolean
+  Returns true if the original destination address of the incoming connection
+  is local to the system, or false if the address doesn't exist on the
+  system. See "dst_is_local" for details.
+
+fc_dst_port : integer
+  Returns an integer value corresponding to the original destination TCP port
+  of the connection on the client side. Only "tcp-request connection" rules may
+  alter this address. See "dst-port" for details.
+
 fc_fackets : integer
   Returns the fack counter measured by the kernel for the client
   connection. If the server connection is not established, if the connection is
@@ -18159,6 +18175,22 @@ fc_sacked : integer
   if the operating system does not support TCP_INFO, for example Linux kernels
   before 2.4, the sample fetch fails.
 
+fc_src : ip
+  This is the original destination IP address of the connection on the client
+  side. Only "tcp-request connection" rules may alter this address. See "src"
+  for details.
+
+fc_src_is_local : boolean
+  Returns true if the source address of incoming connection is local to the
+  system, or false if the address doesn't exist on the system. See
+  "src_is_local" for details.
+
+fc_src_port : integer
+
+  Returns an integer value corresponding to the TCP source port of the
+  connection on the client side. Only "tcp-request connection" rules may alter
+  this address. See "src-port" for details.
+
 
 fc_unacked : integer
   Returns the unacked counter measured by the kernel for the client connection.
@@ -18495,20 +18527,21 @@ so_name : string
   strings instead of integers.
 
 src : ip
-  This is the source IPv4 address of the client of the session. 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. However if the "accept-proxy" or "accept-netscaler-cip" bind
-  directive is used, it can be the address of a client behind another
-  PROXY-protocol compatible component for all rule sets except
-  "tcp-request connection" which sees the real address. When the incoming
-  connection passed through address translation or redirection involving
-  connection tracking, the original destination address before the redirection
-  will be reported. On Linux systems, the source and destination may seldom
-  appear reversed if the nf_conntrack_tcp_loose sysctl is set, because a late
-  response may reopen a timed out connection and switch what is believed to be
-  the source and the destination.
+  This is the source IP address of the client of the session. Any tcp/http
+  rules may alter this address. 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. However if the "accept-proxy" or "accept-netscaler-cip" bind directive
+  is used, it can be the address of a client behind another PROXY-protocol
+  compatible component for all rule sets except "tcp-request connection" which
+  sees the real address. When the incoming connection passed through address
+  translation or redirection involving connection tracking, the original
+  destination address before the redirection will be reported. On Linux
+  systems, the source and destination may seldom appear reversed if the
+  nf_conntrack_tcp_loose sysctl is set, because a late response may reopen a
+  timed out connection and switch what is believed to be the source and the
+  destination.
 
   Example:
        # add an HTTP header in requests with the originating address' country
@@ -18744,9 +18777,10 @@ src_kbytes_out([<table>]) : integer
 
 src_port : integer
   Returns an integer value corresponding to the TCP source port of the
-  connection on the client side, which is the port the client connected from.
-  Usage of this function is very limited as modern protocols do not care much
-  about source ports nowadays.
+  connection on the client side, which is the port the client connected
+  from. Any tcp/http rules may alter this address. Usage of this function is
+  very limited as modern protocols do not care much about source ports
+  nowadays.
 
 src_sess_cnt([<table>]) : integer
   Returns the cumulative number of connections initiated from the incoming
index d167bde86b33eda58987fa2d10a5b24dd346dc61..19edcd243810a923e5989df5ac6074821f0ffd06 100644 (file)
@@ -51,14 +51,20 @@ smp_fetch_src(const struct arg *args, struct sample *smp, const char *kw, void *
 {
        const struct sockaddr_storage *src = NULL;
 
-       if (kw[0] == 'b') {
+       if (kw[0] == 'b') { /* bc_src */
                struct connection *conn = ((obj_type(smp->sess->origin) == OBJ_TYPE_CHECK)
                                           ? cs_conn(__objt_check(smp->sess->origin)->cs)
                                           : (smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)): NULL));
                if (conn && conn_get_src(conn))
                        src = conn_src(conn);
        }
-        else
+       else if (kw[0] == 'f') { /* fc_src */
+               struct connection *conn = objt_conn(smp->sess->origin);
+
+               if (conn && conn_get_src(conn))
+                       src = conn_src(conn);
+       }
+        else /* src */
                src = (smp->strm ? si_src(&smp->strm->si[0]) : sess_src(smp->sess));
 
        if (!src)
@@ -89,14 +95,20 @@ smp_fetch_sport(const struct arg *args, struct sample *smp, const char *kw, void
 {
        const struct sockaddr_storage *src = NULL;
 
-       if (kw[0] == 'b') {
+       if (kw[0] == 'b') { /* bc_src_port */
                struct connection *conn = ((obj_type(smp->sess->origin) == OBJ_TYPE_CHECK)
                                           ? cs_conn(__objt_check(smp->sess->origin)->cs)
                                           : (smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)): NULL));
                if (conn && conn_get_src(conn))
                        src = conn_src(conn);
        }
-        else
+       else if (kw[0] == 'f') { /* fc_src_port */
+               struct connection *conn = objt_conn(smp->sess->origin);
+
+               if (conn && conn_get_src(conn))
+                       src = conn_src(conn);
+       }
+        else /* src_port */
                src = (smp->strm ? si_src(&smp->strm->si[0]) : sess_src(smp->sess));
 
        if (!src)
@@ -118,14 +130,20 @@ smp_fetch_dst(const struct arg *args, struct sample *smp, const char *kw, void *
 {
        const struct sockaddr_storage *dst = NULL;
 
-       if (kw[0] == 'b') {
+       if (kw[0] == 'b') { /* bc_dst */
                struct connection *conn = ((obj_type(smp->sess->origin) == OBJ_TYPE_CHECK)
                                           ? cs_conn(__objt_check(smp->sess->origin)->cs)
                                           : (smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)): NULL));
                if (conn && conn_get_dst(conn))
                        dst = conn_dst(conn);
        }
-        else
+       else if (kw[0] == 'f') { /* fc_dst */
+               struct connection *conn = objt_conn(smp->sess->origin);
+
+               if (conn && conn_get_dst(conn))
+                       dst = conn_dst(conn);
+       }
+        else /* dst */
                dst = (smp->strm ? si_dst(&smp->strm->si[0]) : sess_dst(smp->sess));
 
        if (!dst)
@@ -154,7 +172,16 @@ smp_fetch_dst(const struct arg *args, struct sample *smp, const char *kw, void *
 int smp_fetch_dst_is_local(const struct arg *args, struct sample *smp, const char *kw, void *private)
 {
        struct listener *li = smp->sess->listener;
-       const struct sockaddr_storage *dst = (smp->strm ? si_dst(&smp->strm->si[0]) : sess_dst(smp->sess));
+       const struct sockaddr_storage *dst = NULL;
+
+       if (kw[0] == 'f') { /* fc_dst_is_local */
+               struct connection *conn = objt_conn(smp->sess->origin);
+
+               if (conn && conn_get_src(conn))
+                       dst = conn_dst(conn);
+       }
+       else /* dst_is_local */
+               dst = (smp->strm ? si_dst(&smp->strm->si[0]) : sess_dst(smp->sess));
 
        if (!dst)
                return 0;
@@ -171,7 +198,16 @@ int smp_fetch_dst_is_local(const struct arg *args, struct sample *smp, const cha
 int smp_fetch_src_is_local(const struct arg *args, struct sample *smp, const char *kw, void *private)
 {
        struct listener *li = smp->sess->listener;
-       const struct sockaddr_storage *src = (smp->strm ? si_src(&smp->strm->si[0]) : sess_src(smp->sess));
+       const struct sockaddr_storage *src = NULL;
+
+       if (kw[0] == 'f') { /* fc_src_is_local */
+               struct connection *conn = objt_conn(smp->sess->origin);
+
+               if (conn && conn_get_src(conn))
+                       src = conn_src(conn);
+       }
+       else /* src_is_local */
+               src = (smp->strm ? si_src(&smp->strm->si[0]) : sess_src(smp->sess));
 
        if (!src)
                return 0;
@@ -190,14 +226,20 @@ smp_fetch_dport(const struct arg *args, struct sample *smp, const char *kw, void
 {
        const struct sockaddr_storage *dst = NULL;
 
-       if (kw[0] == 'b') {
+       if (kw[0] == 'b') { /* bc_dst_port */
                struct connection *conn = ((obj_type(smp->sess->origin) == OBJ_TYPE_CHECK)
                                           ? cs_conn(__objt_check(smp->sess->origin)->cs)
                                           : (smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)): NULL));
                if (conn && conn_get_dst(conn))
                        dst = conn_dst(conn);
        }
-        else
+       else if (kw[0] == 'f') { /* fc_dst_post */
+               struct connection *conn = objt_conn(smp->sess->origin);
+
+               if (conn && conn_get_src(conn))
+                       dst = conn_dst(conn);
+       }
+        else /* dst_port */
                dst = (smp->strm ? si_dst(&smp->strm->si[0]) : sess_dst(smp->sess));
 
        if (!dst)
@@ -421,6 +463,15 @@ static struct sample_fetch_kw_list sample_fetch_keywords = {ILH, {
        { "dst",      smp_fetch_dst,   0, NULL, SMP_T_IPV4, SMP_USE_L4CLI },
        { "dst_is_local", smp_fetch_dst_is_local, 0, NULL, SMP_T_BOOL, SMP_USE_L4CLI },
        { "dst_port", smp_fetch_dport, 0, NULL, SMP_T_SINT, SMP_USE_L4CLI },
+
+       { "fc_dst",      smp_fetch_dst,   0, NULL, SMP_T_IPV4, SMP_USE_L4CLI },
+       { "fc_dst_is_local", smp_fetch_dst_is_local, 0, NULL, SMP_T_BOOL, SMP_USE_L4CLI },
+       { "fc_dst_port", smp_fetch_dport, 0, NULL, SMP_T_SINT, SMP_USE_L4CLI },
+
+       { "fc_src",      smp_fetch_src,   0, NULL, SMP_T_IPV4, SMP_USE_L4CLI },
+       { "fc_src_is_local", smp_fetch_src_is_local, 0, NULL, SMP_T_BOOL, SMP_USE_L4CLI },
+       { "fc_src_port", smp_fetch_sport, 0, NULL, SMP_T_SINT, SMP_USE_L4CLI },
+
        { "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 },