From: Christoph Anton Mitterer Date: Fri, 24 Oct 2025 01:36:46 +0000 (+0200) Subject: doc: add overall description of the ruleset evaluation X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=2c6363fb2b6dca8ee7640b6ee6b65a60e8e4d53a;p=thirdparty%2Fnftables.git doc: add overall description of the ruleset evaluation Signed-off-by: Christoph Anton Mitterer Signed-off-by: Florian Westphal --- diff --git a/doc/nft.txt b/doc/nft.txt index b4c889af..4afe8587 100644 --- a/doc/nft.txt +++ b/doc/nft.txt @@ -572,6 +572,95 @@ table inet filter { nft delete rule inet filter input handle 5 ------------------------- +OVERALL EVALUATION OF THE RULESET +--------------------------------- +This is a summary of how the ruleset is evaluated. + +* Even if a packet is accepted by the ruleset it may + still get discarded by other means, for example Linux generally ignores + various ICMP types and there are sysctl options like + `net.ipv{4,6}.conf.*.forwarding` or `net.ipv4.conf.*.rp_filter`. +* Tables are merely a concept of nftables to structure the ruleset. + They are not relevant to the evaluation of the ruleset. +* Packets traverse the network stack and at various hooks (see + <> above for lists of hooks per address family) they’re + evaluated by any base chains attached to these hooks. +* Base chains may call regular chains (via *jump* and *goto*). Regular chains + can call other regular chains. Evaluation continues in the called chain. + Chains residing in a different table cannot be called. +* For each hook, the attached chains are evaluated in order of their priorities. + Chains with lower priority values are evaluated before those with higher ones. + The order of chains with the same priority value is undefined. +* An *accept* verdict (including an implict one via the base chain’s policy) + ends the evaluation of the current base chain. + It is not relevant if the *accept* verdict is issued in the base chain itself + or a regular chain called from the base chain. + The packet advances to the next base chain. + Thus a packet is ultimately accepted if and only if no (matching) rule or base + chain policy issues a *drop* verdict. + All this applies to verdict-like statements that imply *accept*, + for example the NAT statements. +* A *drop* verdict (including an implict one via the base chain’s policy) + immediately ends the evaluation of the whole ruleset. + No further chains of any hook are consulted. + It is therefore not possible to have a *drop* + verdict changed to an *accept* in a later chain. + This also applies to other terminal statements that imply *drop*, for example + *reject*. + Thus, if any base chain uses drop as its policy, the same base chain (or a + regular chain directly or indirectly called by it) must contain at least one + matching *accept* rule or the packet will be dropped. +* Given the semantics of *accept*/*drop* and only with respect to the utlimate + decision of whether a packet is accepted or dropped, the ordering of the + various base chains per hook via their priorities matters only in so far, as + any of them modifies the packet or its meta data and that has an influence on + the verdicts issued by the chains – other than that, the ordering shouldn’t + matter (except for performance and other side effects). + It also means that short-circuiting the ultimate decision is only possible via + *drop* verdicts (respectively verdict-like statements that imply *drop*, for + example *reject*). +* A *jump* verdict causes the current position to be stored in the call stack of + chains and evaluation to continue at the beginning of the called regular + chain. + Called chains must be from the same table and cannot be base chains. + When the end of the called chain is reached, an implicit *return* verdict is + issued. + Other verdicts (respectively verdict-like statements) are processed as + described above and below. +* A *goto* verdict is equal to *jump* except that the current position is not + stored in the call stack of chains. +* A *return* verdict ends the evaluation of the current chain, pops the most + recently added position from the call stack of chains and causes evaluation to + continue after that position. + When there’s no position to pop (which is the case when the current chain is + either the base chain or a regular chain that was reached solely via *goto* + verdicts) it ends the evaluation of the current base chain (and any regular + chains called from it) using the base chain’s policy as implicit verdict. +* Examples for *jump*/*goto*/*return*: + * 'base' {*jump*}→ 'regular-1' {*jump*}→ 'regular-2' + At the end of 'regular-2' or when a *return* is issued in that, evaluation + continues after the *jump* position in 'regular-1'. + At the end of 'regular-1' or when a *return* is issued in that, evaluation + continues after the *jump* position in 'base'. + * 'base' {*jump*}→ 'regular-1' {*goto*}→ 'regular-2' + At the end of 'regular-2' or when a *return* is issued in that, evaluation + continues after the *jump* position in 'base'. + * 'base' {*jump*}→ 'regular-1' {*jump*}→ 'regular-2' {*goto*}→ 'regular-3' + At the end of 'regular-3' or when a *return* is issued in that, evaluation + continues after the *jump* position in 'regular-1'. + At the end of 'regular-1' or when a *return* is issued in that, evaluation + continues after the *jump* position in 'base'. + * 'base' {*jump*}→ 'regular-1' {*goto*}→ 'regular-2' {*goto*}→ 'regular-3' + At the end of 'regular-3' or when a *return* is issued in that, evaluation + continues after the *jump* position in 'base'. +* Verdicts (that is: *accept*, *drop*, *jump*, *goto*, *return* and *continue*) + as well as statements that imply a verdict (like *reject* or the NAT + statements) also end the evaluation of any later statements in their + respective rules (respectively cause an error when loading such rules). + For example in `… counter accept` the `counter` statement is processed, but in + `… accept counter` it is not. + This does not apply to the `comment` statement, which is always evaluated. + SETS ---- nftables offers two kinds of set concepts. Anonymous sets are sets that have no