MINOR: tcp-sample: Add samples to get original info about client connection

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.
This commit is contained in:
Christopher Faulet 2021-10-25 16:58:50 +02:00
parent 7bd21921d1
commit 888cd700f4
2 changed files with 126 additions and 41 deletions

View File

@ -17995,16 +17995,17 @@ cur_tunnel_timeout : integer
"set-timeout" rule has been applied. See also "be_tunnel_timeout". "set-timeout" rule has been applied. See also "be_tunnel_timeout".
dst : ip dst : ip
This is the destination IPv4 address of the connection on the client side, This is the destination IP address of the connection on the client side,
which is the address the client connected to. It can be useful when running which is the address the client connected to. Any tcp/http rules may alter
in transparent mode. It is of type IP and works on both IPv4 and IPv6 tables. this address. It can be useful when running in transparent mode. It is of
On IPv6 tables, IPv4 address is mapped to its IPv6 equivalent, according to type IP and works on both IPv4 and IPv6 tables. On IPv6 tables, IPv4 address
RFC 4291. When the incoming connection passed through address translation or is mapped to its IPv6 equivalent, according to RFC 4291. When the incoming
redirection involving connection tracking, the original destination address connection passed through address translation or redirection involving
before the redirection will be reported. On Linux systems, the source and connection tracking, the original destination address before the redirection
destination may seldom appear reversed if the nf_conntrack_tcp_loose sysctl will be reported. On Linux systems, the source and destination may seldom
is set, because a late response may reopen a timed out connection and switch appear reversed if the nf_conntrack_tcp_loose sysctl is set, because a late
what is believed to be the source and the destination. response may reopen a timed out connection and switch what is believed to be
the source and the destination.
dst_conn : integer dst_conn : integer
Returns an integer value corresponding to the number of currently established Returns an integer value corresponding to the number of currently established
@ -18029,10 +18030,10 @@ dst_is_local : boolean
dst_port : integer dst_port : integer
Returns an integer value corresponding to the destination TCP port of the 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. 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 Any tcp/http rules may alter this address. This might be used when running in
ports to some clients for a whole application session, to stick all users to transparent mode, when assigning dynamic ports to some clients for a whole
a same server, or to pass the destination port information to a server using application session, to stick all users to a same server, or to pass the
an HTTP header. destination port information to a server using an HTTP header.
fc_conn_err : integer fc_conn_err : integer
Returns the ID of the error that might have occurred on the current 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" | | 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 fc_fackets : integer
Returns the fack counter measured by the kernel for the client Returns the fack counter measured by the kernel for the client
connection. If the server connection is not established, if the connection is 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 if the operating system does not support TCP_INFO, for example Linux kernels
before 2.4, the sample fetch fails. 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 fc_unacked : integer
Returns the unacked counter measured by the kernel for the client connection. Returns the unacked counter measured by the kernel for the client connection.
@ -18495,20 +18527,21 @@ so_name : string
strings instead of integers. strings instead of integers.
src : ip src : ip
This is the source IPv4 address of the client of the session. It is of type This is the source IP address of the client of the session. Any tcp/http
IP and works on both IPv4 and IPv6 tables. On IPv6 tables, IPv4 addresses are rules may alter this address. It is of type IP and works on both IPv4 and
mapped to their IPv6 equivalent, according to RFC 4291. Note that it is the IPv6 tables. On IPv6 tables, IPv4 addresses are mapped to their IPv6
TCP-level source address which is used, and not the address of a client equivalent, according to RFC 4291. Note that it is the TCP-level source
behind a proxy. However if the "accept-proxy" or "accept-netscaler-cip" bind address which is used, and not the address of a client behind a
directive is used, it can be the address of a client behind another proxy. However if the "accept-proxy" or "accept-netscaler-cip" bind directive
PROXY-protocol compatible component for all rule sets except is used, it can be the address of a client behind another PROXY-protocol
"tcp-request connection" which sees the real address. When the incoming compatible component for all rule sets except "tcp-request connection" which
connection passed through address translation or redirection involving sees the real address. When the incoming connection passed through address
connection tracking, the original destination address before the redirection translation or redirection involving connection tracking, the original
will be reported. On Linux systems, the source and destination may seldom destination address before the redirection will be reported. On Linux
appear reversed if the nf_conntrack_tcp_loose sysctl is set, because a late systems, the source and destination may seldom appear reversed if the
response may reopen a timed out connection and switch what is believed to be nf_conntrack_tcp_loose sysctl is set, because a late response may reopen a
the source and the destination. timed out connection and switch what is believed to be the source and the
destination.
Example: Example:
# add an HTTP header in requests with the originating address' country # add an HTTP header in requests with the originating address' country
@ -18744,9 +18777,10 @@ src_kbytes_out([<table>]) : integer
src_port : integer src_port : integer
Returns an integer value corresponding to the TCP source port of the 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. connection on the client side, which is the port the client connected
Usage of this function is very limited as modern protocols do not care much from. Any tcp/http rules may alter this address. Usage of this function is
about source ports nowadays. very limited as modern protocols do not care much about source ports
nowadays.
src_sess_cnt([<table>]) : integer src_sess_cnt([<table>]) : integer
Returns the cumulative number of connections initiated from the incoming Returns the cumulative number of connections initiated from the incoming

View 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; 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) struct connection *conn = ((obj_type(smp->sess->origin) == OBJ_TYPE_CHECK)
? cs_conn(__objt_check(smp->sess->origin)->cs) ? cs_conn(__objt_check(smp->sess->origin)->cs)
: (smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)): NULL)); : (smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)): NULL));
if (conn && conn_get_src(conn)) if (conn && conn_get_src(conn))
src = conn_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)); src = (smp->strm ? si_src(&smp->strm->si[0]) : sess_src(smp->sess));
if (!src) 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; 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) struct connection *conn = ((obj_type(smp->sess->origin) == OBJ_TYPE_CHECK)
? cs_conn(__objt_check(smp->sess->origin)->cs) ? cs_conn(__objt_check(smp->sess->origin)->cs)
: (smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)): NULL)); : (smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)): NULL));
if (conn && conn_get_src(conn)) if (conn && conn_get_src(conn))
src = conn_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)); src = (smp->strm ? si_src(&smp->strm->si[0]) : sess_src(smp->sess));
if (!src) 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; 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) struct connection *conn = ((obj_type(smp->sess->origin) == OBJ_TYPE_CHECK)
? cs_conn(__objt_check(smp->sess->origin)->cs) ? cs_conn(__objt_check(smp->sess->origin)->cs)
: (smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)): NULL)); : (smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)): NULL));
if (conn && conn_get_dst(conn)) if (conn && conn_get_dst(conn))
dst = conn_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)); dst = (smp->strm ? si_dst(&smp->strm->si[0]) : sess_dst(smp->sess));
if (!dst) 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) int smp_fetch_dst_is_local(const struct arg *args, struct sample *smp, const char *kw, void *private)
{ {
struct listener *li = smp->sess->listener; 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) if (!dst)
return 0; 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) int smp_fetch_src_is_local(const struct arg *args, struct sample *smp, const char *kw, void *private)
{ {
struct listener *li = smp->sess->listener; 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) if (!src)
return 0; 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; 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) struct connection *conn = ((obj_type(smp->sess->origin) == OBJ_TYPE_CHECK)
? cs_conn(__objt_check(smp->sess->origin)->cs) ? cs_conn(__objt_check(smp->sess->origin)->cs)
: (smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)): NULL)); : (smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)): NULL));
if (conn && conn_get_dst(conn)) if (conn && conn_get_dst(conn))
dst = conn_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)); dst = (smp->strm ? si_dst(&smp->strm->si[0]) : sess_dst(smp->sess));
if (!dst) 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", 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_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 }, { "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", 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_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 }, { "src_port", smp_fetch_sport, 0, NULL, SMP_T_SINT, SMP_USE_L4CLI },