On 26/01/2020 04:18, Lars Noodén wrote:
In nftables, I'd like to apply a rule or set of rules to a very large
number of IP addresses and subnets and looking for the recommended best
practices for that: Should I make a new chain with one address or subnet
per rule, should I use a dictionary, or should I try using a set, or
does it matter? The list would be read at boot but not usually updated
much between boots. Which method would operate most efficiently once
the addresses and subnets are loaded?
It matters. Rather than individual rules, you should definitely use a
set if you can.
Lately, I have been experimenting with methods to populate large sets
from arbitrary sources. I determined that the fastest way should be to
execute a single "add element" command that includes all of the
elements. For newline-delimited input, here is a minimalistic script
demonstrating one way to go about it:-
#!/bin/sh
srcfile=$1
shift
{
echo "flush set $*"
echo "add element $* { "
tr '\n' ',' < "$srcfile"
echo " }"
} | nft -f -
Assuming that this script is saved as "populate-set", it could be used
as follows:-
populate-set mynetworks.txt ip filter mysetname
It works by considering the first parameter as the file to read the list
of addresses/prefixes from, with the remaining parameters being passed
to the "flush set" and "add element" commands. The tr command is used to
convert newline characters to commas, as is required by the syntax of
the add command. Both commands are executed with just one invocation of
nft so that the operation is atomic (in theory).
Alas, I discovered that populating a set with a large number of elements
can cause nft and/or netlink to choke under certain circumstances. To
put "large" into context, I am testing with the IPv6 bogons list, which
consists of over 116000 entries. I reported this issue as
https://bugzilla.netfilter.org/show_bug.cgi?id=1392.
In an attempt to work around this issue, I experimented with executing
multiple "add element" commands in smaller batches but to no avail.
Instead, I found that the only defense is to ensure that out-of-band set
population occurs no more than once after the last "flush ruleset"
command. Otherwise, the population of the set is initially fast, but is
excruciatingly slow on the second and subsequent occasions. Flushing the
entire ruleset seems to obviate the circumstances under which this issue
occurs. Frankly, this instability makes it a nuisance as compared to
working with ipsets.
One other thing to keep in mind is that your set declaration will
require the "interval" flag in order to support (CIDR) prefixes. A lot
of people get confused by that. See
https://bugzilla.netfilter.org/show_bug.cgi?id=1380 as an example.
--
Kerin Millar