How to replace firewalld direct rules with nftables?
Environment
- Red Hat Enterprise Linux 9.5 and later
- firewalld firewall with direct rules
Issue
- What is the replacement for firewall direct rules?
- firewalld considers the direct rule syntax to be deprecated, what do I do for firewall rules which firewalld cannot support?
- How to convert firewalld direct rules to nftables?
Resolution
Note: Design of Rule Ordering
Just like with direct rules, when there are multiple chains using the same hook (eg: the input filter hook) then all those chains are traversed until the packet reaches a drop verdict or reaches the end of the chains.
The nftables wiki page Content from wiki.nftables.org is not included.Base chain priority also explains the behavior:
If a packet is accepted and there is another chain, bearing the same hook type and with a later priority, then the packet will subsequently traverse this other chain. Hence, an accept verdict - be it by way of a rule or the default chain policy - isn't necessarily final. However, the same is not true of packets that are subjected to a drop verdict. Instead, drops take immediate effect, with no further rules or chains being evaluated.
This means that an accept verdict does NOT cause a packet to exit the firewall, but a drop verdict does.
Given a rule setup like:
- nftables - filter priority default, default target accept
- firewalld - filter priority + 10, default target accept, plus explicit
rejectat the end
Packets which reach an nftables drop will exit the firewall and be dropped. Packets which pass an nftables accept will enter firewalld rules.
Given a rule setup like:
- firewalld - filter priority + 10, default target accept, plus explicit
rejectat the end - nftables - filter priority + 20, default target accept
Packets which pass a firewalld accept will enter nftables rules. Packets which reach the firewalld reject will exit the firewall and be dropped. Packets dropped by firewalld will never enter nftables.
Because of this, it makes most sense to:
- Put nftables rules at the default priority, which is less than firewalld's priority +10, so that nftables is evaluated first
- Only use nftables to drop/reject traffic, which is the same caveat that firewalld direct rules had
Converting Rules
List the firewalld direct rules, eg:
# firewall-cmd --direct --get-all-rules
ipv4 filter INPUT 1 -p tcp --dport 9001 -m state --state NEW -j DROP
Observe any table and chains where rules are added.
Tables are named filter, nat, mangle, or raw.
Chains are named INPUT, OUTPUT, FORWARD, PREROUTING, or POSTROUTING.
List the direct rules using -s to get stateless output (no counter values). Direct rules will appear in chains named with capital letters:
# nft -s list ruleset
... firewalld rules omitted ...
table ip filter {
chain INPUT {
type filter hook input priority filter; policy accept;
tcp dport 9001 ct state new counter drop
}
}
Any table/chain where direct rules were defined, copy that table/chain to a file, and save it in the nftables configuration location /etc/sysconfig/nftables.conf.
Ensure this rules file has flags persist in the table:
/etc/sysconfig/nftables.conf
flush ruleset
table ip filter {
flags persist;
chain INPUT {
type filter hook input priority filter; policy accept;
tcp dport 9001 ct state new counter drop;
}
}
Delete old Direct Rules from firewalld
Once direct rules have been moved from firewalld to nftables, remove the old rule from firewalld:
# firewall-cmd --direct --remove-rule ipv4 filter INPUT 1 -p tcp --dport 9001 -m state --state NEW -j DROP
# firewall-cmd --runtime-to-permanent
Start the nftables systemd service
Both firewalld and nftables services can now be started together, and they will not override the other's rules:
# systemctl enable --now nftables.service
Verify Rules
# nft -s list ruleset
table inet firewalld { # progname firewalld
flags owner,persist
... firewalld rules omitted ...
}
table ip filter {
flags persist
chain INPUT {
type filter hook input priority filter; policy accept;
tcp dport 9001 ct state new counter drop
}
}
Root Cause
firewalld direct rules use the old iptables interface to the kernel's netfilter firewall. iptables is deprecated and will eventually be removed from the Linux Kernel and from RHEL.
The supported interface to add rules to the firewall is nftables. firewalld is an easy user interface to nftables.
Due to the hook-based nature of nftables, it is possible to run both the firewalld and the nftables service together where each service applies its own firewall rules. This is one advantage that nftables has over iptables - many different participants (firewalld, podman, libvirt, etc) could add their own firewall rules without affecting the other participants.
To work with rules in the nftables firewall, some knowledge of nftables command and rule syntax is required. Red Hat and community references are available at:
- RHEL 9 - Configuring firewalls and packet filters - Getting started with nftables
- Content from wiki.nftables.org is not included.Quick reference - nftables in 10 minutes
- Content from wiki.nftables.org is not included.Simple rule management
RHEL 9.5 adds the owner and persist flags to nftables which allows both firewalld and nftables services to each add their own firewall rules without disturbing the other service's rules.
This solution is part of Red Hat’s fast-track publication program, providing a huge library of solutions that Red Hat engineers have created while supporting our customers. To give you the knowledge you need the instant it becomes available, these articles may be presented in a raw and unedited form.