-
Notifications
You must be signed in to change notification settings - Fork 0
Home
NFTBan is an open-source Linux Intrusion Prevention System (IPS) and firewall manager built on nftables, designed to integrate cleanly with modern Linux security stacks.
NFTBan enforces protection through nftables kernel rules. All packet decisions (accept, drop, bypass) happen in the kernel. Userspace components (daemon, CLI) write to kernel sets and present kernel-derived state. They do not enforce.
NFTBan is defined by:
- Kernel state — the source of truth (what is actually enforcing)
- Validator interpretation — derives health from kernel evidence
- Vocabulary — frozen terminology contract (v1.81)
- Module contracts — per-module evidence rules and structural requirements
- CI gates — automated enforcement of these contracts
When sources disagree, higher priority wins. Always.
| Priority | Source | Role |
|---|---|---|
| 1 (highest) |
Kernel (nft list ruleset) |
What is actually enforcing right now |
| 2 |
Validator (nftban-validate --json) |
Derives health state from kernel. Authoritative for interpretation. |
| 3 |
CLI (nftban status, nftban health) |
Renders validator output. Never computes truth independently. |
| 4 (lowest) |
Config (/etc/nftban/conf.d/) |
Operator intent. May disagree with kernel. |
NFTBan evaluates module health through a 4-axis model, then applies a fifth consistency axis at system level. Each enabled module is checked on four independent axes:
| Axis | What it checks | Values |
|---|---|---|
| Config | Is the module intended to be on? | ENABLED / DISABLED |
| Structural | Do the kernel objects exist? | PRESENT / MISSING |
| Runtime | Is the required daemon running? | RUNNING / STOPPED / ERROR |
| Effective | Is the module taking action? | ENFORCING / OBSERVING / IDLE |
| Consistency | Do config and kernel agree? | OK / MISMATCH |
A fifth axis, Consistency, checks config-vs-kernel agreement after module evaluation. ENABLED + MISSING = MISMATCH (DEGRADED). DISABLED + PRESENT = valid residual (OK).
The overall system reports one of four health states:
| State | Meaning | Exit code |
|---|---|---|
| PROTECTED | All axes pass, system capable of enforcement | 0 |
| IDLE | All axes pass, no relevant traffic observed | 0 |
| DEGRADED | One or more axes fail, partial protection | 1 |
| DOWN | Critical failure, no viable protection | 2 |
Precedence: DOWN > DEGRADED > IDLE > PROTECTED.
For the full derivation logic, see Health Model.
Every claim about system state must trace to one of these evidence types:
| Evidence | What it proves | Strength |
|---|---|---|
| Kernel counter > 0 | Enforcement action occurred (drops, rate limits) | Strong |
| Kernel set population > 0 | Classification or ban entries exist | Strong |
| Kernel structure exists | Chain, set, or table is present | Weak (presence only, not effectiveness) |
| Journal/log event | Detection or ban event occurred | Context-dependent (external to validator) |
| Config value | Operator intended this state | Intent only (not truth) |
- Counter > 0 = POSITIVE evidence (something happened)
- Counter = 0 = NEUTRAL (proves nothing — not failure)
- Structure exists does NOT mean module is effective
- Shared counters cannot be attributed to specific modules
- Aggregate counters cannot be used for module-level claims
| Module | Layer | Evidence | Strength | Daemon |
|---|---|---|---|---|
| DDoS Protection | L3/L4 | 5 dedicated kernel counters | Strong | NO |
| BotGuard | L7 HTTP | 6 dedicated kernel sets | Strong | YES |
| Portscan Detection | L3/L4 | Structure only (no counter) | None (validator cannot prove enforcement) | NO |
| Login Monitoring | L2 Auth | Journal events + shared sets | Outside validator (journal not read) | YES |
| Blacklist & Threat Intelligence | L1 IP | Shared sets + shared counters | Mixed | Partial |
Additional modules (not part of the validator truth model — external integrations):
| Module | Type | Notes |
|---|---|---|
| Suricata IDS | L7 DPI | External integration, EVE JSON events |
| DNS Tunnel Suspicion | Advisory | Non-blocking, detection only |
The Go validator (nftban-validate) is a point-in-time kernel snapshot tool.
It reads nft -j list ruleset, evaluates the 4-axis model, and emits findings.
What the validator can prove:
- Kernel objects exist (tables, chains, sets, counters)
- Counter values (enforcement evidence for DDoS)
- Set population (enforcement evidence for BotGuard, blacklist)
- Service state (daemon running or stopped)
- Config-kernel consistency (enabled vs present)
What the validator cannot prove:
- Portscan enforcement (no dedicated counter exists)
- LoginMon enforcement (journal events outside validator scope)
- Feed-vs-geoban attribution (shared counter)
- LoginMon-vs-operator-ban attribution (shared counter)
- BotGuard module registration in daemon (journal check not performed)
- GeoIP database freshness beyond file existence
The validator does not observe journal, logs, or daemon internals. It is a kernel snapshot tool only. Absence of validator evidence is not evidence of absence — a module may be actively enforcing while the validator reports IDLE.
Key consequence: Some modules report IDLE due to validator scope, not lack of activity. IDLE means "no validator-observable evidence," not "module inactive."
For the full per-module scope analysis, see Known Limitations.
These rules hold at all times and are enforced by CI gates:
-
Kernel is the only enforcement authority. All packet decisions happen in nftables. Userspace cannot override a kernel verdict.
-
CLI must never override validator truth (INV-CONS-001). If the validator says DEGRADED, the CLI must say DEGRADED. No softening, no reinterpretation.
-
Zero counters are neutral, not failure. Counter = 0 proves nothing. It must never be interpreted as degradation or absence of attacks.
-
Structure does not imply protection. Chain exists does not mean module is effective. Set exists does not mean enforcement is happening.
-
Shared counters cannot be used for attribution.
input_blacklist_dropproves blacklist-family enforcement but cannot attribute to feeds or geoban.input_blacklist_manual_dropcannot attribute to LoginMon or portscan. -
Config is intent, not truth. ENABLED in config does not mean PRESENT in kernel. DISABLED in config does not mean MISSING from kernel (residual state is valid).
-
Disabled + present = valid residual. A module disabled in config but present in kernel is in a valid residual state, not a consistency failure.
This specification is enforced by automated CI gates. Any gate violation blocks the build.
| Gate category | What it enforces |
|---|---|
| Vocabulary | No banned terms in CLI output |
| Truth consistency | CLI output matches validator JSON |
| Schema integrity | Required kernel objects in codegen |
| Module contracts | Per-module structural and evidence rules |
| Evidence enforcement | No ENFORCING without counter/set proof |
| Config-kernel consistency | Mismatch detection works correctly |
| CLI contract | CLI respects trust level boundaries |
For the full gate specification, see CI_GATE_SPEC_v1.82.md.
| Property | Value |
|---|---|
| Version | 1.83.0 |
| License | MPL-2.0 |
| Repository | github.com/itcmsgr/nftban |
| Architecture | Go + Shell hybrid (~90K Go, ~99K Shell) |
| Enforcement | nftables kernel (63 counters, ~19 sets, 7 anchors per family) |
| Daemon |
nftband (Go) — writes to kernel sets, runs loginmon + BotGuard |
| Validator |
nftban-validate (Go) — read-only, ~1ms, frozen JSON schema |
| CLI |
nftban (Shell) — 119 command handlers, presentation layer |
# Check system health (kernel-derived truth)
nftban health
# Check full validator output
nftban-validate --json
# Enable modules
nftban ddos enable
nftban portscan enable
nftban botguard enable
nftban login enable
nftban geoban enable- DDoS Protection | BotGuard | Portscan
- Login Monitoring | Blacklist & Threat Intelligence
- Suricata IDS | DNS Tunnel Suspicion
# 1. System health (kernel-derived truth)
nftban-validate --json | jq '.status'
# "protected" / "idle" / "degraded" / "down"
# 2. Kernel structure exists
nft list tables
# Must show: "table ip nftban" and "table ip6 nftban"
# 3. Pipeline anchors intact
nft list chain ip nftban input | grep ANCHOR
# Must show 7 anchors: HYGIENE → TRUSTED → BAN → ESTABLISHED → DETECT → SERVICE → FINAL
# 4. Module enforcement evidence
nft list counter ip nftban input_syn_rate_exceeded
# Counter > 0 = DDoS ENFORCING. Counter = 0 = NEUTRAL.
# 5. CLI agrees with validator (INV-CONS-001)
nftban health
# Must show same status as validatorMozilla Public License 2.0 (MPL-2.0) Copyright 2024-2026 NFTBAN Project
NFTBan Wiki
Getting Started
Architecture
Modules
- BotGuard (HTTP L7)
- DDoS Protection (L3/L4)
- Portscan Detection
- Login Monitoring
- Blacklist & Threat Intelligence
- Suricata IDS Integration
- DNS Tunnel Suspicion
Operator Reference
- CLI Commands Reference
- Configuration Reference
- Systemd Units & Timers
- Optimization & Tuning
- Security Operations Guide
- GeoIP Database Guide
- FHS Compliance
- Troubleshooting: Smoke & Selftest
Verification & Trust
- Glossary & Vocabulary
- Known Limitations
- Metrics & Evidence Model
- Binary Verification (SLSA)
- Security Architecture
Reference
Legal