# CSF AlmaLinux 10: nftables and ipset Problems Fixed

Source: https://srvscripts.com/guides/csf-almalinux-10-nftables-ipset/
Updated: 2026-10-03
Publisher: srvScripts (https://srvscripts.com/)

AlmaLinux 10 and the rest of the EL10 family finished the move that EL9 started: the legacy iptables kernel modules are gone, `iptables` is a thin front-end that translates into nftables, and `ipset` in particular no longer does what CSF expects. CSF was written against the old stack and, although every maintained fork now runs on EL10, the experience ranges from “works with caveats” to “silently not blocking”. This guide explains what changed, how to see it on your server and how to configure around it.

In short: On EL10 iptables is a front-end to nftables and ipset no longer creates working sets, so with LF_IPSET = “1” CSF reports thousands of blocked addresses while the kernel drops none.

**Short answer:** On EL10 `iptables` is a front-end to nftables and `ipset` no longer creates working sets, so with `LF_IPSET = "1"` CSF reports thousands of blocked addresses while the kernel drops none. Set `LF_IPSET = "0"`, keep `DENY_IP_LIMIT` around 500, disable remote blocklists and run `csf -ra`; then prove a test deny appears in `nft list ruleset`. For large blocklists on a panel-free server use the Aetherinox fork’s nftables wrapper, or move to firewalld with fail2ban.

## What the compatibility layer does and does not do

On EL9 and EL10, `iptables` is really `iptables-nft`. Each legacy rule CSF writes is translated into an nftables expression inside a table called `ip filter`. For plain rules that works fine, and a `csf -r` on EL10 produces a working chain. Confirm which flavour you are on:

```
iptables -V
alternatives --display iptables 2>/dev/null | head -3
nft list tables
```

You should see `(nf_tables)` in the version string and tables named `ip filter`, `ip6 filter` and possibly `ip nat` after CSF starts. If `nft list tables` is empty while CSF claims to be running, the rules never landed.

The part that does not translate is ipset. CSF uses ipset when `LF_IPSET = "1"`, and the deny-list handling for large blocklists depends on it for performance. On EL10 the userspace `ipset` tool talks to a kernel interface that is either absent or wrapped in a way that returns success without creating a functional set, so CSF thinks it loaded thousands of addresses and the kernel drops none of them.

## Symptoms

- `csf -r` completes without errors, but a deliberately denied IP can still connect.

- `ipset list` prints sets with zero members, or fails with a netlink error.

- `/var/log/lfd.log` shows blocklist refresh messages with large counts that never match anything.

- `csf -g 203.0.113.10` reports the address in `csf.deny` but the chain lookup shows no rule.

Test it directly. Add a throwaway deny for an address you control, then look for it in nftables rather than trusting CSF’s own report:

```
csf -d 203.0.113.10 test
nft list ruleset | grep -c 203.0.113.10
```

A zero from the second command on a server where `LF_IPSET = "1"` is the confirmation.

## The immediate workaround

Turn ipset off in CSF so every deny becomes an individual rule that the compat layer can translate:

```
sed -i 's/^LF_IPSET = .*/LF_IPSET = "0"/' /etc/csf/csf.conf
csf -ra
```

This works and blocks correctly, but the cost is scale. Each address becomes a rule, and a chain with tens of thousands of rules slows every packet decision. Keep `csf.deny` short and let `DENY_IP_LIMIT` do its job:

```
DENY_IP_LIMIT = "500"
DENY_TEMP_IP_LIMIT = "200"
```

With those limits and no remote blocklists (which you should have disabled anyway after CVE-2026-65639, see the [hardening guide](/guides/hardening-csf-messenger-remote-lists/)), the rule count stays manageable and LFD’s brute-force blocking keeps working normally.

## Choose a fork that knows about nftables

The original CSF v15.00 and the cPanel fork both take the iptables-nft route described above. The Aetherinox csf-firewall project added a wrapper that can emit native nftables rules and handles sets through `nft` rather than `ipset`, which restores efficient large-list handling on EL10. On a server with no panel, or with CyberPanel or Webmin, that is the least disruptive fix. On cPanel, stay on the cPanel fork and accept the `LF_IPSET = "0"` trade-off, because mixing forks on a cPanel host breaks the RPM update path.

If you are building fresh EL10 servers and do not have a decade of `csf.conf` to preserve, it is worth stepping back and running firewalld with fail2ban, which are nftables-native and packaged by the distribution. Our [firewalld and fail2ban tutorial](/guides/replace-csf-with-firewalld-fail2ban/) walks through it on both AlmaLinux 9 and 10.

## Do not run firewalld alongside CSF

Fresh AlmaLinux 10 installs enable firewalld, and on a cPanel or DirectAdmin server it must be disabled before CSF starts, otherwise both write to nftables and the result depends on which started last:

```
systemctl disable --now firewalld
systemctl mask firewalld
csf -ra
```

`nft list tables` should then show only CSF’s tables. If you see a table named `inet firewalld`, firewalld is still active.

## Kernel module note

The compat layer needs `nf_tables`, `nft_compat` and the `xt_*` match modules loaded. On hardened hosts where `kernel.modules_disabled = 1` was set early in boot (a sensible mitigation after the 2026 kernel LPEs, see [our mitigation guide](/guides/copy-fail-dirty-frag-mitigation/)), CSF may fail to add a rule that needs a module not yet loaded. Load them explicitly before locking modules:

```
cat > /etc/modules-load.d/csf.conf
