I am using firewalld on RHEL 8, and need to add a few nftable rules as well.
(The nftable rules are based on the answer to CentOS 8 as NAT router with nft and firewalld - how to get it to pass TFTP?)
In a running firewall, this works well with the nft -f command.
However, this gets lost on a reboot.
The RedHat documentation (behind paywall) suggests using the nftables.service service to load rules on reboot, but this does not work in conjunction with firewalld. The two services are listed as conflicting, and even if they weren't, firewalld would likely flush the nftable rules.
Is there another way to get the nftable rules to load on restart?
The firewalld utility, when using the nftables backend, will not flush tables that don't belong to it:
The same has just to be done when managing other tables.
Actually in the previous answer, it's already done: the nftables rules idempotently deletes only their own table:
handletftp
.Sadly, that's not the case for
nftables.service
for the stop action:One must just ensure that the stop part of the systemd service doesn't directly flush all rules while still doing the job. This job will be delegated into dedicated nftables rules for the stop action.
So here's a practical method: duplicate (eg:
systemctl cat nftables.services
) and alternftables.service
into an instantiated version[email protected]
to be put in/etc/systemd/system/[email protected]
:Create the dedicated configuration directory used above:
Place rules that for each table defined, always start like this, so loading the rules is independent of other tables and idempotent (example with tables
ip foo
andbridge bar
):or just use one table per file. The
flush ruleset
statement is prohibited since it's global.The reason a table is created, deleted and recreated is to get the result idempotent: while deleting a non-existing table is an error and would atomically make the whole loading fail, declaring an existing table without defining it (by adding an empty table) never fails and does nothing except creating it empty if it didn't exist before. In both cases (didn't exist at boot, exists at reload) delete can now work, leaving the place to really define the table right after. All this is happening in the same transaction and is still atomic: no packet will ever be evaluated with a missing ip foo table if it existed before during this.
Prepare a stop version of above that will only delete (here the empty declarations aren't strictly needed and could be removed if there was only one table, but should be kept if there's more than one table: failure is for the whole transaction):
and put everything in their location:
This can now be activated with:
Example from previous OP's question:
in
/etc/nftables/idempotent/handletftp.nft
:In
/etc/nftables/idempotent/stop-handletftp.nft
Enabling and starting it:
Stopping it:
which will leave firewalld's rules in place. Likewise, stopping or restarting firewalld will leave these rules in place.
There are probably improvements to do:
nf_nat_tftp
which won't be done automatically (contrary tonf_conntrack_tftp
which is automatically loaded from reference in the rules or contrary to firewalld which would loadnf_nat_tftp
explicitly). So related but non-strictly nftables configurations should be kept in mind (this one setting could simply be put in/etc/modules-load.d/
).