firewalld direct rules with ACCEPT not working on RHEL 8, 9 and 10

Solution Verified - Updated

Environment

  • Red Hat Enterprise Linux 8
  • Red Hat Enterprise Linux 9
  • Red Hat Enterprise Linux 10
  • firewalld (with default nftables backend)
  • Direct firewall rule with -j ACCEPT to allow traffic

Issue

  • Direct rules with ACCEPT verdict not working with nftables backend
  • Even though httpd.service and firewalld.service are running, allowing port 80 through direct rules does not provide access to the webserver:

    systemctl start httpd.service
    systemctl start firewalld.service 
    firewall-cmd --direct --add-rule ipv4 filter INPUT 1 -p tcp --dport 80 -j ACCEPT
    
  • Client can't accesss, gets No route to host error.

  • Changing from FirewallBackend=nftables to FirewallBackend=iptables the direct rule works.

  • Connectivity not working between servers when firewall getting started in RHEL8

  • firewalld direct.xml from RHEL 7 no longer works on RHEL 8

  • How do direct rules work with firewalld when firewalld uses nftables?

Resolution

This is expected behaviour due to the way the nftables firewall works, as explained in the below Root Cause section.

It is necessary to change the firewall rules to match the behaviour of the firewall.

The following options are recommended ways to resolve this:

  • Any traffic with a direct -j ACCEPT rule should also be allowed in the firewalld firewall
  • Don't use -j ACCEPT in direct rules, make sure allowed traffic is handled by firewalld
  • Change to use the nftables service directly, instead of firewalld plus direct rules

The following options are possible but not recommended:

  • Change firewalld to use the iptables backend, with FirewallBackend=iptables in firewalld.conf
  • Change to use the iptables service only, instead of firewalld plus direct rules

Root Cause

The man 5 firewalld.direct manual page contains the following explanation:

CAVEATS
    Depending on the value of FirewallBackend (see firewalld.conf(5)) direct
    rules behave differently in some scenarios.

    Packet accept/drop precedence
        Due to implementation details of netfilter inside the kernel, if
        FirewallBackend=nftables is used direct rules that ACCEPT packets don't
        actually cause the packets to be immediately accepted by the system.
        Those packets are still be subject to firewalld's nftables ruleset. This
        basically means there are two independent firewalls and packets must be
        accepted by both (iptables and nftables). As an aside, this scenario also
        occurs inside of nftables (again due to netfilter) if there are multiple
        chains attached to the same hook - it's not as simple as iptables vs nftables.

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 was discusssed with Fedora development on This content is not included.Red Hat Bug 1837129 - Direct rules with ACCEPT verdict not working with nftables backend and CLOSED CANTFIX a known documented behaviour change between iptables and nftables.

Category

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.