Skip to content

EL10: require kernel-modules-extra, fail safe when the state match is unusable, fix csftest probe-rule leak - #13

Open
zeroth-blip wants to merge 3 commits into
Black-HOST:mainfrom
zeroth-blip:fix/el10-kernel-modules-extra
Open

EL10: require kernel-modules-extra, fail safe when the state match is unusable, fix csftest probe-rule leak#13
zeroth-blip wants to merge 3 commits into
Black-HOST:mainfrom
zeroth-blip:fix/el10-kernel-modules-extra

Conversation

@zeroth-blip

Copy link
Copy Markdown
Contributor

Fixes #12.

Background

On EL10-family systems (AlmaLinux/Rocky/RHEL 10+) the xt_* netfilter kernel modules moved to the separate kernel-modules-extra package, which minimal installs do not include. Verified end-to-end on a fresh AlmaLinux 10.2 minimal + cPanel box: without that package there are two distinct failure modes depending on FASTSTART:

  • FASTSTART = "1" — fails open. iptables-nft-restore rejects the whole atomic batch, csf dies mid-start (-A INVDROP into a chain that was never created), exit 1, firewall left completely empty with ACCEPT policies. No outage, but zero protection.
  • FASTSTART = "0" — fails closed with exit 0. Rules apply one-by-one: every conntrack ESTABLISHED/RELATED accept fails, while DROP policies, bare DROPs and simple dport rules succeed (~157 partial rules). Result: all outbound TCP dead (replies dropped inbound — no conntrack), while ICMP and DNS to configured resolvers keep working via explicit per-IP bidirectional rules. csf reports success. This is the exact symptom reported in AlmaLinux 10.2: Outbound TCP traffic blocked after enabling CSF (TCP_OUT rules not applied / conntrack rules fail with iptables-nft) #12.

Installing kernel-modules-extra for the running kernel and rebooting fully resolves it (csftest all-OK, complete ruleset loads, verified by SSH-ing in through the live firewall).

What this PR does

1. install.sh — pre-flight before dispatching to the panel installers
Probes for a working -m conntrack / -m state match. On EL10-family it attempts dnf install kernel-modules-extra-$(uname -r) (with an unversioned fallback) and re-probes; if the match still doesn't work it aborts with clear remediation steps instead of completing an install that cannot work. On non-EL10 platforms a failing probe prints a loud warning and the install continues, preserving existing behaviour (also keeps the containerised CI matrix green, where the host kernel provides the modules).

2. csftest.pl — actionable diagnostics + probe-rule leak fix

  • Probe rules are now deleted unconditionally after every insert attempt. Previously a test that "failed" with only a warning (iptables-nft can insert successfully while still printing Extension ... not supported) skipped its cleanup and leaked e.g. -A OUTPUT -p tcp --dport 9999 -j ACCEPT into the live ruleset.
  • When failures look like missing kernel modules, it now prints what to actually do: on EL10-family, dnf install kernel-modules-extra-$(uname -r) + reboot; elsewhere a generic missing-xt-modules note.

3. csf.pl — never apply a broken ruleset (the real lesson from #12)
New checkstatemodule() pre-flight in dostart(), run before any rules or policies are applied: it verifies the configured state module actually works (IPv4, and IPv6 when IPV6_SPI is enabled), and on failure goes through error() — policies reset to ACCEPT, /etc/csf/csf.error written, exit 1 — with an actionable message. This turns the silent full outage into a loud refusal on both FASTSTART paths. Skipped when LF_SPI/IPV6_SPI are disabled (monolithic-kernel VPS setups that legitimately run without the state match). The probe rule is removed even when the insert reports failure, so it cannot leak.

Testing

  • Full unit test suite passes (prove -r .github/tests/unit/ — 15 files, 83 tests).
  • csftest.pl exercised against a shimmed iptables simulating the broken-EL10 output: all 11 probes now get matching deletes (no leak), EL10 note prints on PLATFORM_ID=platform:el10, generic note elsewhere, healthy path unchanged.
  • install.sh check exercised for all four paths: healthy → silent continue; broken non-EL10 → warn + continue; broken EL10 + remediation fails → abort exit 1; broken EL10 + remediation succeeds → continue.
  • checkstatemodule() exercised in isolation: healthy path passes and cleans up both probes; failure path calls error() with the expected message and still attempts cleanup.
  • Real-world repro and fix confirmed on AlmaLinux 10.2 minimal + cPanel 11.136 (see AlmaLinux 10.2: Outbound TCP traffic blocked after enabling CSF (TCP_OUT rules not applied / conntrack rules fail with iptables-nft) #12 write-up).

…extra on EL10

EL10-family minimal installs (AlmaLinux/Rocky/RHEL 10+) moved the xt_*
netfilter kernel modules to the separate kernel-modules-extra package,
which is not installed by default. Without it csf's stateful ruleset
cannot be created and enabling the firewall can block all outbound TCP
while reporting success.

Probe for a working conntrack/state match before dispatching to the
panel installers. On EL10-family, attempt to install
kernel-modules-extra for the running kernel and abort with clear
remediation steps if the match still does not work. On other platforms
print a loud warning and continue, preserving existing behaviour.
…lures

csftest.pl only deleted its probe rules when a test passed. On
iptables-nft an insert can succeed while still printing a warning (for
example on EL10 without kernel-modules-extra, where the extension
revision probe fails but the rule is translated natively), so a
"failed" test could leak its probe rule - e.g. a stray
'-A OUTPUT -p tcp --dport 9999 -j ACCEPT' - into the live ruleset.
Run the delete unconditionally after every insert attempt.

When failures look like missing kernel modules, print an actionable
note instead of leaving the user with the cryptic "Extension revision 0
not supported" warnings: on EL10-family systems point directly at
'dnf install kernel-modules-extra-$(uname -r)' + reboot, otherwise a
generic missing-xt-modules explanation.
If the kernel cannot use the state/conntrack match (e.g. EL10-family
minimal installs without kernel-modules-extra), starting the firewall
is destructive in both startup modes:

- FASTSTART=1: iptables-nft-restore rejects the atomic batch, csf dies
  mid-start with the firewall left empty (fails open)
- FASTSTART=0: rules apply one-by-one, the ESTABLISHED/RELATED accepts
  all fail while DROP policies and plain DROP rules succeed, silently
  blocking all outbound TCP - and csf still exits 0 (fails closed while
  reporting success)

Add a pre-flight check in dostart() that verifies the configured state
module actually works before any rules or policies are applied. On
failure csf now fails safe through error() - policies reset to ACCEPT,
csf.error written, exit 1 - with an actionable message that points at
kernel-modules-extra on EL10-family systems. The probe rule is removed
even if the insert reports a failure so it can never leak into the
ruleset.
@UptimeEnforcer

Copy link
Copy Markdown
Member

@zeroth-blip thanks for the PR, there are couple of things that we should address prior to the merge.

  1. I believe the changes in install.sh can be simplified and more importantly moved into installer.sh -> install_dependencies so the package installers can take over of the unnecessary code complexity

  2. At first thought checkstatemodule in csf.pl is a neat idea, but as it resets policies to ACCEPT on error it got me thinking, what if OS update or user action removes these kernel modules, will this open up the whole server wide open or after the server reboots?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

AlmaLinux 10.2: Outbound TCP traffic blocked after enabling CSF (TCP_OUT rules not applied / conntrack rules fail with iptables-nft)

2 participants