From: Willy Tarreau Date: Thu, 1 Jan 2026 09:26:23 +0000 (+0100) Subject: MINOR: net_helper: add an option to ip.fp() to append the source address X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=a206f85f966f70f3301ea796a525cb634a9482a5;p=thirdparty%2Fhaproxy.git MINOR: net_helper: add an option to ip.fp() to append the source address The new value 4 will permit to append the source address to the fingerprint, making it easier to build rules checking a specific path. --- diff --git a/doc/configuration.txt b/doc/configuration.txt index 8dab2c865..7a3b19274 100644 --- a/doc/configuration.txt +++ b/doc/configuration.txt @@ -21146,15 +21146,18 @@ ip.fp([]) - 1: the received TTL value is appended to the fingerprint (1 byte) - 2: the list of TCP option kinds, as returned by "tcp.options_list", made of 0 to 40 extra bytes, is appended to the fingerprint + - 4: the source IP address is appended to the fingerprint, which adds + 4 bytes for IPv4 and 16 for IPv6. - Example: + Example: make a 12..24 bytes fingerprint using the base FP, the TTL and the + source address (1+4=5): frontend test mode http bind :4445 tcp-ss 1 tcp-request connection set-var(sess.syn) fc_saved_syn http-request return status 200 content-type text/plain lf-string \ - "src=%[var(sess.syn),ip.src] fp=%[var(sess.syn),ip.fp,hex]\n" + "src=%[var(sess.syn),ip.src] fp=%[var(sess.syn),ip.fp(5),hex]\n" See also "fc_saved_syn", "tcp-ss", "eth.data", "ip.df", "ip.ttl", "tcp.win", "tcp.options.mss", and "tcp.options_list". diff --git a/src/net_helper.c b/src/net_helper.c index 49a0d5ed4..19cea3a6d 100644 --- a/src/net_helper.c +++ b/src/net_helper.c @@ -659,6 +659,7 @@ static int sample_conv_tcp_win(const struct arg *arg_p, struct sample *smp, void static int sample_conv_ip_fp(const struct arg *arg_p, struct sample *smp, void *private) { struct buffer *trash = get_trash_chunk(); + char *ipsrc; uchar ipver; uchar iptos; uchar ipttl; @@ -698,6 +699,7 @@ static int sample_conv_ip_fp(const struct arg *arg_p, struct sample *smp, void * pktlen = read_n16(smp->data.u.str.area + 2); ipdf = !!(smp->data.u.str.area[6] & 0x40); ipttl = smp->data.u.str.area[8]; + ipsrc = smp->data.u.str.area + 12; } else if (ipver == 6) { /* check fields for IPv6 */ @@ -712,6 +714,7 @@ static int sample_conv_ip_fp(const struct arg *arg_p, struct sample *smp, void * iptos = read_n16(smp->data.u.str.area) >> 4; ipdf = 1; // no fragments by default in IPv6 ipttl = smp->data.u.str.area[7]; + ipsrc = smp->data.u.str.area + 8; } else return 0; @@ -800,6 +803,13 @@ static int sample_conv_ip_fp(const struct arg *arg_p, struct sample *smp, void * write_n16(trash->area + 3, tcpwin); write_n16(trash->area + 5, tcpmss); + /* mode 4: append source IP address */ + if (mode & 4) { + iplen = (ipver == 4) ? 4 : 16; + memcpy(trash->area + trash->data, ipsrc, iplen); + trash->data += iplen; + } + /* option kinds if any are stored starting at offset 7 */ smp->data.u.str = *trash; smp->flags &= ~SMP_F_CONST;