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".
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

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;
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 },