I can't find any documentation that would explain the syntax and evaluation of the following sample constructs:
add rule filter output tcp flags & (syn | ack) == syn | ack
add rule filter output tcp flags & (fin | syn) != 0
I did read @A.B answer here: logging TCP flags.
This only explains the purpose of those constructs (matching TCP
flags), but I'd like to know the syntax and how the evaluation of the expressions together with operators work.
Particularly the meaning of "bitwise" operators and how they're evaluated in the flags
expressions as whole.
Also it's not clear to me what != 0
does and in particular the purpose of &
operator upfront.
I know they're OR, AND etc. but don't understand how this applies in nftables
rule.
Some more complex examples could help too.
1 Answer 1
Using bitwise operators in this fashion is a common approach to extract specific bit values. Thus with TCP flags, if you only care about SYN and ACK (???A??S?
), you "and" the flags with "SYN or ACK", which clears all other flags (000A00S0
). You can then compare the result with 0 if you only care whether one of the bits is set, or with a specific combination of flags if you want an exact match.
In the first rule, the expression is tcp flags & (syn | ack) == syn | ack
. Working up by precedence:
(syn | ack)
calculates the combination of bits representing SYN or ACKtcp flags & (syn | ack)
calculates the intersection of the TCP flags and "SYN or ACK": the result is only the SYN and/or ACK flags, if one or both are settcp flags & (syn | ack) == syn | ack
compares the result of the previous expression withsyn | ack
The overall effect is that the expression returns true if both SYN and ACK flags are set. All other flags are ignored.
Another way of looking at it is this:
SYN in flags | ACK in flags | Flags & (SYN or ACK) | SYN or ACK | == |
---|---|---|---|---|
0 | 0 | 00 | 11 | False |
0 | 1 | 01 | 11 | False |
1 | 0 | 10 | 11 | False |
1 | 1 | 11 | 11 | True |
In the second rule, the expression is tcp flags & (fin | syn) != 0
. Working up again:
(fin | syn)
calculates the combination of bits representing FIN or SYNtcp flags & (fin | syn)
calculates the intersection of the TCP flags and "FIN or SYN": the result is only the FIN and/or SYN flags, if one or both are set (theoretically; in practice only one can be set)tcp flags & (fin | syn) != 0
succeeds if the result of the previous expression is non-zero
The overall effect is that the expression returns true if either FIN or SYN flags are set. All other flags are ignored.
Another way of looking at it is this:
FIN in flags | SYN in flags | Flags & (FIN or SYN) | != 0 |
---|---|---|---|
0 | 0 | 00 | False |
0 | 1 | 01 | True |
1 | 0 | 10 | True |
1 | 1 | 11 | True |
-
Can we omit the upfront
&
operator such that it'stcp flags (syn | ack)
? I assume this will mean that eitherSYN
orACK
is matched but not both right? and btw. can operators other than&
be put in front offlags
? ex.tcp flags == (syn | ack)
?metablaster– metablaster2024年08月14日 07:42:28 +00:00Commented Aug 14, 2024 at 7:42 -
What do you mean by "upfront"?Stephen Kitt– Stephen Kitt2024年08月14日 09:25:09 +00:00Commented Aug 14, 2024 at 9:25
-
in the
flags &
the&
operator is in front offlags
, this is what I meant by "upfront" of the rest of expression that follows, sorry for bad English. the&
operator is put "upfront" of the rest of bitwise expression. (I call it upfront because my understanding is according to how bitwise expressions works in C\C++metablaster– metablaster2024年08月14日 10:17:05 +00:00Commented Aug 14, 2024 at 10:17 -
1It’s supposed to be read left-to-right, so in
flags &
,flags
comes first, then the&
operator, same as in C.Stephen Kitt– Stephen Kitt2024年08月14日 10:20:02 +00:00Commented Aug 14, 2024 at 10:20 -
Ah, I definitely get it now, therefore
flags | syn
orflags == syn
are valid expressions, soflags
IS part of bitwise expression. I very much appreciate you answer!metablaster– metablaster2024年08月14日 10:47:45 +00:00Commented Aug 14, 2024 at 10:47