[prev in list] [next in list] [prev in thread] [next in thread] 

List:       netfilter
Subject:    Re: Could somebody please explain priorities correctly and in an understandable way?
From:       Binarus <lists () binarus ! de>
Date:       2023-03-02 7:58:04
Message-ID: a8692a29-d289-6359-a66d-3c8b6d49946e () binarus ! de
[Download RAW message or body]

At first, thank you very much for your long and detailed answer! At 
least I now know that I am not alone :-)

On 01.03.2023 17:05, Kerin Millar wrote:
> Indeed, this amounts to a very shoddy experience. Through experimentation, I \
> discovered that the priority number is a signed 32-bit integer and that, for "type \
> nat hook prerouting", the permissible range of priority values appears to be -199 \
> through to 2147483647 (that is, 2 ^ 31 - 1). I consider this to be a bug, in so far \
> as neither of these things or explained by - or can be discerned by - reading the \
> nft(8) manual. At best, it states that "not all names make sense in every family \
> with every hook", without explaining why or what the exact constraints are. The \
> compatibility matrix beneath shows the symbolic names for various priority values, \
> along with where they are conventionally used, yet leaves the reader none the wiser \
> as to what, precisely, the constraints are. 
> In a sense, the real problem is that it's a leaky abstraction; it doesn't abstract \
> away the requirement to understand Netfilter internals for the numeric values to be \
> fully understood in turn. Take -300 ("raw") as an example. Assigning that to a \
> prerouting hook will have its respective chain be traversed prior to connection \
> tracking operations. But why? Presumably because it's below a certain threshold \
> yet, even being an experienced nftables user, I find myself unable to explain. As \
> concerns iptables, the consideration of priority values is fully abstracted by the \
> requirement to make use of built-in chains, albeit at the cost of not being able to \
> employ an equivalent hook more than once.

That's exactly what I think, too.

> For the time being, my advice would be to stick to using the symbolic names.

Usually I prefer symbolic names over hard-coded values. The problem here 
is that I don't know what name I should use in what situation.

For example, in the table you mentioned there are no less than eight 
rows for the ip family that contain the prerouting hook as "typical", 
each of them denoting a different priority. Five of these rows contain a 
symbolic name for the respective priority. It seems that we must read 
the "description" column in that table and must guess from it what row 
matches a certain tuple of family, chain type and hook (and possibly, 
rule actions) best.

Or, looking at it from the opposite perspective: For example, for what 
combination of family, chain type and hook would the keyword "raw" 
(priority -300) be appropriate? Does the answer to that question also 
depend on the actions the rules in the chain perform? That would be 
weird, because then most chains could only contain a very limited number 
of rules that perform "similar" (priority-wise) actions.

I even wouldn't be surprised any more if rules would misbehave because 
they are in a chain with wrong priority. For example, a rule dealing 
with fragmented packets (I don't know whether such a thing is possible, 
but let's assume it for a moment) probably must run with priority lower 
than -400. I can very well imagine that this rule would do nothing if 
it's in a chain with higher priority without letting you know; that is, 
without making nft throw errors when loading that rule. Of course, that 
would be catastrophic.

The more I think about it, the more worrying it becomes, and the less 
trust I have in nft.

> For instance, your hook could be written as "type nat hook prerouting dstnat". In \
> the course of transitioning to nftables, you may find it useful to inspect how \
> built-in iptables chains end up being translated. 
> # nft flush ruleset; iptables-nft -t nat -A PREROUTING; nft list ruleset
> table ip nat {
> 	chain PREROUTING {
> 		type nat hook prerouting priority dstnat; policy accept;
> 		counter packets 0 bytes 0
> 	}
> }
> # nft -n list ruleset
> table ip nat {
> 	chain PREROUTING {
> 		type nat hook prerouting priority -100; policy accept;
> 		counter packets 0 bytes 0
> 	}
> }

Thank you very much for that example. I am regularly using that method 
when trying to learn :-)

> 
> In the case that you require for multiple hooks of the same type, it's worth noting \
> that priority values can be expressed in relative terms. For instance, "dstnat - 1" \
> would translate as -101 and would be within range. As concerns the effects of \
> relative priority values, I think that \
> https://wiki.nftables.org/wiki-nftables/index.php/Configuring_chains#Base_chain_priority \
> constitutes the best material that is currently on offer.

I have seen that page, but it doesn't help with the basic problem.

Since nft is an undocumented black box, I currently can't use it. I 
can't accept the risk of unexpected behavior, given that nft is used to 
configure firewalls, which are typically the core of information 
security. Since your answer is still the only one, I have to assume that 
there indeed is no better documentation somewhere else.

We now have no other option than dropping the project and sticking with 
our current firewall scripts based on iptables. Too sad that we already 
have put substantial time in trying to learn nft ... we'll revisit it in 
one or two years and see whether the documentation has been improved then.

In every case, thanks a lot again, and best regards,

Binarus


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic