can be used to distinguish between multiple apparently identical hosts. The
real-world use case is to refine the identification of misbehaving hosts
between a shared IP address to avoid blocking legitimate users when only one
- is misbehaving and needs to be blocked. The converter builds a 7-byte binary
- block based on the input. The bytes of the fingerprint are arranged like
- this:
+ is misbehaving and needs to be blocked. The converter builds a 8-byte minimum
+ binary block based on the input. The bytes of the fingerprint are arranged
+ like this:
- byte 0: IP TOS field (see ip.tos)
- byte 1:
- bit 7: IPv6 (1) / IPv4 (0)
- bits 3..0: TCP window scaling + 1 (1..15) / 0 (no WS advertised)
- byte 3..4: tcp.win
- byte 5..6: tcp.options.mss, or zero if absent
+ - byte 7: 1 bit per present TCP option, with options 2 to 8 being mapped to
+ bits 0..6 respectively, and bit 7 indicating the presence of any
+ option from 9 to 255.
The <mode> argument permits to append more information to the fingerprint. By
default, when the <mode> argument is not set or is zero, the fingerprint is
- solely made of the 7 bytes described above. If <mode> is specified as another
+ solely made of the 8 bytes described above. If <mode> is specified as another
value, it then corresponds to the sum of the following values, and the
respective components will be concatenated to the fingerprint, in the order
below:
- 4: the source IP address is appended to the fingerprint, which adds
4 bytes for IPv4 and 16 for IPv6.
- Example: make a 12..24 bytes fingerprint using the base FP, the TTL and the
+ Example: make a 13..25 bytes fingerprint using the base FP, the TTL and the
source address (1+4=5):
frontend test
/* Builds a binary fingerprint of the IP+TCP input contents that are supposed
* to rely essentially on the client stack's settings. This can be used for
* example to selectively block bad behaviors at one IP address without
- * blocking others. The resulting fingerprint is a binary block of 56 to 376
- * bytes long (56 being the fixed part and the rest depending on the provided
+ * blocking others. The resulting fingerprint is a binary block of 64 to 384
+ * bits long (64 being the fixed part and the rest depending on the provided
* TCP extensions).
*/
static int sample_conv_ip_fp(const struct arg *arg_p, struct sample *smp, void *private)
uchar tcpflags;
uchar tcplen;
uchar tcpws;
+ uchar opts;
ushort pktlen;
ushort tcpwin;
ushort tcpmss;
else
return 0;
- /* prepare trash to contain at least 7 bytes */
- trash->data = 7;
+ /* prepare trash to contain at least 8 bytes */
+ trash->data = 8;
/* store the TOS in the FP's first byte */
trash->area[0] = iptos;
(tcpflags >> 6 << 0); // CWR, ECE
tcpmss = tcpws = 0;
+ opts = 0;
ofs = 20;
while (ofs < tcplen) {
size_t next;
+ uchar opt;
if (smp->data.u.str.area[ofs] == 0) // kind0=end of options
break;
break;
/* option is complete, take a copy of it */
+ opt = smp->data.u.str.area[ofs];
+
if (mode & 2) // mode & 2: append tcp.options_list
- trash->area[trash->data++] = smp->data.u.str.area[ofs];
+ trash->area[trash->data++] = opt;
- if (smp->data.u.str.area[ofs] == 2 /* MSS */) {
+ if (opt == 2 /* MSS */) {
tcpmss = read_n16(smp->data.u.str.area + ofs + 2);
}
- else if (smp->data.u.str.area[ofs] == 3 /* WS */) {
+ else if (opt == 3 /* WS */) {
tcpws = (uchar)smp->data.u.str.area[ofs + 2];
/* output from 1 to 15, thus 0=not found */
tcpws = tcpws > 14 ? 15 : tcpws + 1;
}
+
+ /* keep a presence mask of opts 2..8 and others */
+ if (opt >= 2)
+ opts |= 1 << (opt < 9 ? opt - 2 : 7);
+
ofs = next;
}
write_n16(trash->area + 3, tcpwin);
write_n16(trash->area + 5, tcpmss);
+ /* the the bit mask of present options */
+ trash->area[7] = opts;
+
/* mode 4: append source IP address */
if (mode & 4) {
iplen = (ipver == 4) ? 4 : 16;