Fail2ban + nftables = stderr: 'Error: Could not process rule: No such file or directory'

Moritz asked:

I’ve got a problem combining fail2ban and nftables. My setup is "Debian 10 + fail2ban + nftables".
At the end there is a problem adding a new rule if someone is banned by fail2ban:

2020-09-15 17:38:26,078 fail2ban.utils          [626]: Level 39 7fa684124198 -- exec: nft list chain inet fail2ban fail2ban | grep -q '@f2b-sshd[ \t]'
2020-09-15 17:38:26,078 fail2ban.utils          [626]: ERROR   7fa684124198 -- stderr: 'Error: Could not process rule: No such file or directory'
2020-09-15 17:38:26,078 fail2ban.utils          [626]: ERROR   7fa684124198 -- stderr: 'list chain inet fail2ban fail2ban'
2020-09-15 17:38:26,078 fail2ban.utils          [626]: ERROR   7fa684124198 -- stderr: '                ^^^^^^^^'
2020-09-15 17:38:26,078 fail2ban.utils          [626]: ERROR   7fa684124198 -- returned 1

My nftables.conf looks like this

include "/etc/nftables/fail2ban.conf"

#!/usr/sbin/nft -f

# Start by flushing all the rules.
flush ruleset

# Define private IP for ssh access
define privateip = {77.56.188.228}

table inet filter {
    # TCP ports to allow. (Allowed services: HTTP, HTTPS, SFTP)
    set tcp_accepted {
        type inet_service; flags interval;
        elements = {
        80,443,722
        }
    }
    # TCP port for SSH service.
    set ssh_accepted {
        type inet_service; flags interval;
        elements = {
        721
        }
    }
    # UDP ports to allow. (Allowed services: Teamspeak 3)
    set udp_accepted {
        type inet_service; flags interval;
        elements = {
        9987
        }
    }
    chain input {
        # This line set what traffic the chain will handle, the priority and default policy.
        # The priority comes in when you in another table have a chain set to "hook input" and want to specify in what order they should run.
        # Use a semicolon to separate multiple commands on one row.
        type filter hook input priority 0; policy drop;

        # Limit ping requests.
        ip protocol icmp icmp type echo-request limit rate over 1/second burst 5 packets drop
        ip6 nexthdr icmpv6 icmpv6 type echo-request limit rate over 1/second burst 5 packets drop

        # OBS! Rules with "limit" need to be put before rules accepting "established" connections.
        # Allow all incomming established and related traffic. Drop invalid traffic.
        ct state established,related accept
        ct state invalid drop

        # Allow loopback.
        # Interfaces can by set with "iif" or "iifname" (oif/oifname). If the interface can come and go use "iifname", otherwise use "iif" since it performs better.
        iif lo accept

        # Drop all fragments.
        ip frag-off & 0x1fff != 0 counter drop

        # Force SYN checks.
        tcp flags & (fin|syn|rst|ack) != syn ct state new counter drop

        # Drop XMAS packets.
        tcp flags & (fin|syn|rst|psh|ack|urg) == fin|syn|rst|psh|ack|urg counter drop

        # Drop NULL packets.
        tcp flags & (fin|syn|rst|psh|ack|urg) == 0x0 counter drop

        # Allow certain inbound ICMP types (ping, traceroute).
        # With these allowed you are a good network citizen.
        # Without the nd-* ones ipv6 will not work.
        ip protocol icmp icmp type { destination-unreachable, echo-reply, echo-request, source-quench, time-exceeded } accept      
        ip6 nexthdr icmpv6 icmpv6 type { destination-unreachable, echo-reply, echo-request, nd-neighbor-solicit,  nd-router-advert, nd-neighbor-advert, packet-too-big, parameter-problem, time-exceeded } accept

        # Allow SSH for specific IP only
        ip saddr $privateip tcp dport @ssh_accepted accept
        tcp dport @ssh_accepted drop

        # Allow needed tcp and udp ports.
        tcp dport @tcp_accepted ct state new accept
        udp dport @udp_accepted ct state new accept
    }
    chain forward {
        type filter hook forward priority 0; policy drop;

        # Forward all established and related traffic. Drop invalid traffic.
        ct state established,related accept
        ct state invalid drop
    }
    chain output {
        type filter hook output priority 0; policy drop;

        # Allow all outgoing traffic. Drop invalid traffic.
        # ipv6 ICMP needs to be explicitly allowed here.
        ip6 nexthdr ipv6-icmp accept
        ct state new,established,related accept
        ct state invalid drop
    }
}

and the fail2ban.conf looks like this

#!/usr/sbin/nft -f

# Use ip as fail2ban doesn't support ipv6 yet
table ip fail2ban {
        chain input {
                # Assign a high priority to reject as fast as possible and avoid more complex rule evaluation
                type filter hook input priority 100;
        }
}

It looks like the command is not finding the "fail2ban" table but to be honest, I don’t know where to look or fix the problem. If you need more information please ask

My answer:


You’re defining a table fail2ban in family ip, but fail2ban is expecting a table fail2ban in family inet (which basically means dual stack). Because it doesn’t exist, nftables is returning the error No such file or directory.

The comment # Use ip as fail2ban doesn't support ipv6 yet seems to be old, as current versions of fail2ban have IPv6 support, including the version in Debian 10.

But I think something else is wrong, because fail2ban should be creating the nftables chain and related ipsets automatically. Check that you didn’t alter or delete the file action.d/nftables.conf shipped by fail2ban, or override it with your own *.local file.

Also check that at least one jail has banaction = nftables (of any type), and no jails use the deprecated nftables-multiport or nftables-allports. These should instead be nftables[type=multiport] or nftables[type=allports] respectively.


View the full question and any other answers on Server Fault.

Creative Commons License
This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License.