]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: net_helper: add an option to ip.fp() to append the source address
authorWilly Tarreau <w@1wt.eu>
Thu, 1 Jan 2026 09:26:23 +0000 (10:26 +0100)
committerWilly Tarreau <w@1wt.eu>
Thu, 1 Jan 2026 09:32:16 +0000 (10:32 +0100)
The new value 4 will permit to append the source address to the
fingerprint, making it easier to build rules checking a specific path.

doc/configuration.txt
src/net_helper.c

index 8dab2c865f281eebc34a47b2ae6ec49b7fd1429b..7a3b19274b018e46efa679300fea5041c7c1c96f 100644 (file)
@@ -21146,15 +21146,18 @@ ip.fp([<mode>])
     -   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".
index 49a0d5ed45133108996ac1cf51c416ef4cd87f82..19cea3a6d4c9e6bc7d1f14eda32d61644a181c85 100644 (file)
@@ -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;