← All rules
SOCLE-CLD-NET-001// Firewallmediumeffective runtime

Ensure the Host Firewall Defaults to Deny (any backend)

The host firewall must apply a default-deny policy on inbound traffic: whatever is not explicitly allowed is dropped. Pavois accepts any backend, and checks the loaded ruleset for an nftables input chain with policy drop, or an iptables -P INPUT DROP / REJECT default target.

Checked against the resolved running state (e.g. sshd -T, sysctl, systemctl show), catches drop-ins and Includes a file read would miss. Caveat: runtime ≠ persistence; a value correct now may not survive a reboot.

A pass proves✓ running now? on disk? survives rebootthe qualified verdict →

This domain is thinly covered by Pavois today, see coverage.

Debian 12CIS 1.1.0Debian 13CIS 1.0.0FedoraRHEL 10 / Rocky 10 / AlmaLinux 10RHEL 8 / Rocky 8 / AlmaLinux 8CIS 4.0.0RHEL 9 / Rocky 9 / AlmaLinux 9CIS 2.0.0Ubuntu 24.04CIS 1.0.0Ubuntu 26.04
One check, maps to 3 standards

Pavois asserts the effective configuration, the live, resolved state, not a file. File-based scanners (OVAL/SCAP, Lynis) miss Includes, drop-ins and runtime defaults; this check sees what is actually applied.

A mapping is a cross-reference to where each standard places this requirement, anchored and cross-validated, not a claim of equivalence. A passing check is evidence toward these references, how to read it.

What Pavois checks

Pavois inspects the loaded ruleset (nft list ruleset, falling back to iptables -S INPUT), which is what the kernel actually enforces on each packet. Reading /etc/nftables.conf or /etc/ufw/ would only prove that a policy exists on disk: a ruleset that was never loaded, a firewall service that failed to start, or a ruleset flushed by another tool would all be reported compliant while the host sits wide open. Note reboot_survivable: no for this reason: a live policy drop is only durable if the firewall service is enabled at boot, which is exactly what the Pavois remediation does.

describe command('if nft list ruleset 2>/dev/null | grep -qE \'hook input.*policy drop\' || iptables -S INPUT 2>/dev/null | grep -qE \'^-P INPUT (DROP|REJECT)\'; then echo ok; else echo ko; fi') do
  its('stdout.strip') { should eq 'ok' }
end

How to verify it is applied

On an nftables host, confirm the input hook drops by default and that SSH is still explicitly allowed:

nft list ruleset | grep -E 'hook input|dport 22'
#   type filter hook input priority 0; policy drop;
#   ip saddr { 203.0.113.0/24 } tcp dport 22 accept

On an iptables/ufw host, iptables -S INPUT | head -1 must print -P INPUT DROP. Also confirm the ruleset comes back after a reboot: systemctl is-enabled nftables (or ufw / firewalld) returns enabled.

Inspect & investigate

A policy drop is silent: nftables does not log dropped packets unless you add an explicit log prefix rule before the policy. Use nft list ruleset -a counters, or ufw logging on (which writes to /var/log/ufw.log and the kernel log), to see what the default policy is actually rejecting. The firewall service's own lifecycle (a failed ruleset load, a syntax error) is in journalctl -u nftables / -u firewalld / -u ufw, and that is where a silently unprotected host shows up.

Remediation

The Pavois plan exposes this rule as a choice of backend (choose:): nftables (default), firewalld or ufw. With nftables, Pavois installs the package and writes a complete ruleset: policy drop on input and forward, accept on output, plus loopback, ct state established,related, a drop of ct state invalid, ICMP/ICMPv6, and an SSH allow rule that Pavois injects itself. Set ssh_allow_from: [203.0.113.0/24] on the rule in the plan and the rule becomes ip saddr { 203.0.113.0/24 } tcp dport 22 accept (with the ufw backend: ufw allow from 203.0.113.0/24 to any port 22 proto tcp, run before ufw --force enable). If you leave ssh_allow_from empty, SSH is opened to everyone: that is the deliberate safe default, so a plan that forgets it never locks the administrator out. The firewall is brought up before the rest of the converge, and Pavois enables the service so the ruleset is reloaded at boot.

This rule belongs to an exclusive group: only one firewall daemon is kept, and the ones nobody picked are disabled once, after every control of the group has spoken.

Pavois applies this with its own harden engine, the plan below, not a shell script:

defaultnftables
optionsfirewalld: package: firewalld, service: firewalld, nftables: package: nftables, ruleset: #!/usr/sbin/nft -f flush ruleset table inet filter { chain input { type filter hook input priority 0; policy drop; iif "lo" accept ct state established,related accept ct state invalid drop ip protocol icmp accept ip6 nexthdr ipv6-icmp accept %SSH_RULE% } chain forward { type filter hook forward priority 0; policy drop; } chain output { type filter hook output priority 0; policy accept; } } , service: nftables, ssh_rule: tcp dport 22 accept, ssh_rule_from: ip saddr { %CIDRS% } tcp dport 22 accept, ufw: enable_cmd: %SSH_ALLOW%; /usr/sbin/ufw --force enable; systemctl enable --now ufw, package: ufw, service: ufw, ssh_allow: /usr/sbin/ufw allow OpenSSH 2>/dev/null; /usr/sbin/ufw allow 22/tcp 2>/dev/null, ssh_allow_from: /usr/sbin/ufw allow from %SRC% to any port 22 proto tcp 2>/dev/null
resourcechoose
pavois harden plan local

where the target is local, a user@host SSH alias, or a container , Docs

Impact & precautions

This rule can cut you off from the machine. A default-deny input policy applied without an SSH accept rule ends every remote session and refuses the next one, permanently: on a headless host or a cloud instance with no console, the machine is lost. Before applying:

  • Set ssh_allow_from in the plan to the CIDR of your administration network (or leave it empty to keep port 22 open to all): Pavois injects the accept rule into the ruleset it writes, and it is your only guarantee of getting back in.
  • Keep a second session or a console open, then open a new SSH session to confirm access before closing the original.
  • Do not run two firewalls. nftables and firewalld/ufw enabled together end up cancelling each other out (measured on a real host: both installed, both dead, zero protection). Pavois resolves the exclusive group once, but a firewall configured by hand outside Pavois can reintroduce the conflict.
  • Beware of interactions with kmod-loading-disabled. The ct state rules need nf_conntrack; if module loading has already been locked (kernel.modules_disabled=1) and the module is not loaded, the ruleset fails to load and the host ends up with no firewall, or no SSH.
  • Any service you publish (HTTP, database replication, monitoring agent) needs its own accept rule: inventory your listening ports (ss -tulpn) before switching the policy.

Standards mapping

StandardReferenceTypeVersionConfidence
CIS4.2.7, 4.3.8, 4.4.2.1directper OS, see the benchmark tablehigh
NISTCA-3(5), CM-7(b), SC-7(23), CM-6(a)supporting800-53 Rev 5 · 800-171 Rev 2 (pinned)medium
PCI DSS1.3.1supporting4.0.1medium

Each reference is a cross-reference anchored in the upstream benchmark and cross-validated against the SCAP Security Guide and ansible-lockdown, not a claim of equivalence. Direct = a prescriptive, line-level requirement; supporting = an abstract control family (NIST) the check provides evidence toward. How to read a mapping.

Sources & references