-
Notifications
You must be signed in to change notification settings - Fork 2
Configuration Reference
Type: Configuration Scope: All configuration files, load order, and relationship to runtime truth Files:
/etc/nftban/(base) +conf.d/(per-module) Terminology: Glossary & Vocabulary Last verified: v1.218.7
This page defines NFTBan's configuration structure, load order, and the relationship between configuration and runtime behavior.
Critical principle: Configuration is operator intent, not runtime truth.
A config file saying DDOS_ENABLED="true" means the operator intends DDoS
to be enabled. It does NOT mean DDoS chains exist in the kernel, enforcement
is happening, or the module is PRESENT. Only the kernel (via the Go validator)
proves what is actually enforcing.
For how config relates to health state, see Health Model. For system structure and truth authority, see Architecture. For CLI behavior, see CLI Commands Reference. For term definitions, see Glossary.
Configuration may be:
- Incorrect — operator set a wrong value
- Incomplete — not all required keys are present
- Stale — config was changed but rebuild not performed
- Inconsistent with kernel — config says ENABLED but kernel objects are MISSING
These are real operational states. The health model handles each:
| Config state | Kernel state | Health interpretation |
|---|---|---|
| ENABLED | PRESENT | Normal — config intent realized |
| ENABLED | MISSING | DEGRADED — VAL-CONS-001 (config/kernel mismatch) |
| DISABLED | PRESENT | Valid residual — kernel objects persist from prior enable |
| DISABLED | MISSING | Expected — config and kernel agree |
The only way to verify runtime state is kernel evidence:
# Config says DDoS is enabled (intent):
grep DDOS_ENABLED /etc/nftban/conf.d/ddos/main.conf.local
# Kernel proves whether DDoS is actually present (truth):
nft list chain ip nftban ddos_protection
# Validator derives the health interpretation:
nftban validate --json | jq '.modules.ddos'/etc/nftban/
├── main.conf # Master system config
├── conf.d/
│ ├── {module}/
│ │ ├── main.conf # Module base config (package-provided)
│ │ ├── main.conf.local # Module operator overrides (survives upgrades)
│ │ ├── classic.conf # Mode-specific parameters
│ │ └── suricata.conf # Suricata integration parameters
│ ├── feeds/ # Feed source configs (one .conf per feed)
│ ├── panels/ # Panel integration
│ └── {feature}.conf # Feature-level configs
├── whitelist.d/ # Whitelist IP files
└── blacklist.d/ # Blacklist IP files
1. conf.d/{module}/main.conf ← base (package-provided, overwritten on upgrade)
2. conf.d/{module}/main.conf.local ← operator override (survives upgrades)
.local wins. If both files define the same key, .local takes precedence.
The base main.conf is overwritten on package upgrades. The .local file is
the safe place for operator customization.
- Config files are read at: module enable, firewall rebuild, daemon restart
- Config is not authoritative at runtime — once rules are loaded into the kernel, the kernel state is truth regardless of subsequent config changes
- Config changes do NOT take effect until an explicit action (enable, rebuild, restart) applies them to the kernel
| Scenario | Behavior |
|---|---|
.local missing, base exists |
Base config used |
| Both missing | Module defaults to DISABLED |
| Key missing from file | Default value used (defined per key below) |
| File unreadable (permissions) | Module defaults to DISABLED (silent) |
Invalid value (e.g., "maybe") |
Treated as "false" (fail-safe to DISABLED) |
| Duplicate key in same file | Last occurrence wins (shell source behavior) |
| Syntax error in file | File fails to source; module defaults to DISABLED |
These master switches control the config axis for each module.
| Property | Value |
|---|---|
| File |
conf.d/botguard/main.conf (.local override) |
| Default | "false" |
| Values |
"true" / "false"
|
| Axis effect | Config: ENABLED or DISABLED |
| Kernel effect | None until nftban botguard enable or nftban firewall rebuild
|
| If ENABLED + kernel MISSING | DEGRADED (VAL-CONS-001) |
| If DISABLED + kernel PRESENT | Valid residual |
| Property | Value |
|---|---|
| File |
conf.d/ddos/main.conf (.local override) |
| Default | "false" |
| Values |
"true" / "false"
|
| Axis effect | Config: ENABLED or DISABLED |
| Kernel effect | None until nftban ddos enable or nftban firewall rebuild
|
| If ENABLED + kernel MISSING | DEGRADED (VAL-CONS-001) |
| If DISABLED + kernel PRESENT | Valid residual (kernel chains continue enforcing) |
| Property | Value |
|---|---|
| File |
conf.d/ddos/main.conf (.local override) |
| Default | "auto" |
| Values |
"auto" / "classic" / "hybrid"
|
| Axis effect | None (mode selection, not enable/disable) |
| Failure mode | Invalid mode → falls back to classic |
| Property | Value |
|---|---|
| File |
conf.d/portscan/main.conf (.local override) |
| Default | "false" |
| Values |
"true" / "false"
|
| Axis effect | Config: ENABLED or DISABLED |
| Kernel effect | None until nftban portscan enable or nftban firewall rebuild
|
| If ENABLED + kernel MISSING | DEGRADED (VAL-CONS-001) |
| If DISABLED + kernel PRESENT | Valid residual (chain continues logging) |
| Property | Value |
|---|---|
| File |
conf.d/portscan/main.conf (.local override) |
| Default | "auto" |
| Values |
"auto" / "classic" / "suricata" / "hybrid"
|
| Axis effect | None (mode selection) |
| Property | Value |
|---|---|
| File |
conf.d/login_alert.conf (.local override) |
| Default | "false" |
| Values |
"true" / "false"
|
| Axis effect | Config: ENABLED or DISABLED |
| Runtime dependency | Requires nftband daemon RUNNING |
| If ENABLED + daemon STOPPED | DEGRADED (VAL-SERVICE-001) |
| Property | Value |
|---|---|
| File |
conf.d/login_alert.conf (.local override) |
| Default | "true" |
| Values |
"true" / "false"
|
| Effect | Enables/disables SSH auth failure detection within LoginMon |
| Property | Value |
|---|---|
| File |
conf.d/geoban/main.conf (.local override) |
| Default |
"true" — GeoBan is enabled by default, but ships with GEOBAN_DEFAULT_POLICY="allow" (block only listed countries). With no countries configured it is enabled-but-IDLE and blocks nothing; add countries to activate blocking. |
| Values |
"true" / "false"
|
| Axis effect | Config: ENABLED or DISABLED |
| Data dependency | Requires GeoIP database at /var/lib/nftban/geoip/dbip-country-lite.mmdb
|
| If ENABLED + DB missing | STALE (VAL-GEOBAN-001 finding emitted) |
| Zero countries configured | Valid IDLE — not a failure |
These control detection sensitivity. They affect behavior after the next detection cycle — they do NOT affect kernel rules directly.
| Key | File | Default | Meaning |
|---|---|---|---|
PORTSCAN_CLASSIC_MIN_PORTS |
portscan/classic.conf |
5 |
Unique ports to begin tracking an IP |
PORTSCAN_CLASSIC_TIME_WINDOW |
portscan/classic.conf |
60 (seconds) |
Detection aggregation window |
PORTSCAN_CLASSIC_VERTICAL_PORTS |
portscan/classic.conf |
10 |
Ports on one host → vertical scan |
PORTSCAN_CLASSIC_VERTICAL_WINDOW |
portscan/classic.conf |
60 (seconds) |
Window for vertical detection |
PORTSCAN_CLASSIC_HORIZONTAL_TARGETS |
portscan/classic.conf |
5 |
Hosts probed on one port → horizontal scan |
PORTSCAN_CLASSIC_HORIZONTAL_WINDOW |
portscan/classic.conf |
30 (seconds) |
Window for horizontal detection |
PORTSCAN_CLASSIC_ACTION |
portscan/classic.conf |
"block" |
Action on detection: block/log |
| Key | File | Default | Meaning |
|---|---|---|---|
PORTSCAN_CLASSIC_BAN_VERTICAL |
portscan/classic.conf |
1800 (30 min) |
Vertical scan ban |
PORTSCAN_CLASSIC_BAN_HORIZONTAL |
portscan/classic.conf |
3600 (1 hour) |
Horizontal scan ban |
PORTSCAN_CLASSIC_BAN_BLOCK |
portscan/classic.conf |
7200 (2 hours) |
Block range scan ban |
PORTSCAN_CLASSIC_BAN_STROBE |
portscan/classic.conf |
600 (10 min) |
Strobe scan ban |
PORTSCAN_CLASSIC_BAN_DEFAULT |
portscan/classic.conf |
1800 (30 min) |
Default ban duration |
PORTSCAN_CLASSIC_PROGRESSIVE_BAN |
portscan/classic.conf |
"true" |
Enable progressive escalation |
PORTSCAN_CLASSIC_PROGRESSIVE_MULTIPLIER |
portscan/classic.conf |
2 |
Repeat offender multiplier |
PORTSCAN_CLASSIC_PROGRESSIVE_MAX |
portscan/classic.conf |
86400 (24 hours) |
Maximum ban duration |
| Key | File | Default | Meaning |
|---|---|---|---|
HTTP_BOT_TRIP_CONN |
botguard/main.conf |
200 |
Connections to trigger scoring |
HTTP_BOT_CLEAR_CONN |
botguard/main.conf |
150 |
Connections to clear suspect |
HTTP_BOT_EMERGENCY_CONN |
botguard/main.conf |
500 |
Connections to trigger emergency |
HTTP_BOT_SUSPECT_RATE |
botguard/main.conf |
"30/second" |
Rate to mark as suspect |
HTTP_BOT_SUSPECT_BURST |
botguard/main.conf |
60 |
Burst allowance for suspect marking |
HTTP_BOT_SUSPECT_TIMEOUT |
botguard/main.conf |
"5m" |
Suspect set entry timeout |
HTTP_BOT_FAST_LOOP_INTERVAL |
botguard/main.conf |
60 (seconds) |
Scoring loop interval |
| Key | File | Default | Meaning |
|---|---|---|---|
GEOBAN_ATOMIC |
geoban/main.conf |
"true" |
Atomic set replacement on sync |
GEOBAN_DEFAULT_POLICY |
geoban/main.conf |
"allow" |
Default: allow all, block configured |
GEOBAN_LOGGING |
geoban/main.conf |
"true" |
Log geoban operations |
Feeds are configured in one file, and there is a master switch — it ships off.
| Property | Value |
|---|---|
| Location |
/etc/nftban/conf.d/feeds.conf — a single flat file |
| Master switch |
NFTBAN_FEEDS_ENABLED — ships "false", opt-in |
| Feed sources | variables in that same file, pattern FEED_<NAME>_<PROPERTY>; sources are auto-discovered by scanning for FEED_*_URL
|
| Per-feed enable | FEED_<NAME>_ENABLED |
| Managed by |
nftban feeds enable <name> · nftban feeds select (interactive) |
| Override |
/etc/nftban/nftban.conf.local (global), not a feeds.conf.local
|
| Shared set | Feeds load into blacklist_ipv4/ipv6 (shared with GeoBan) |
| Shared counter |
input_blacklist_drop (shared with GeoBan — non-attributable) |
⛔ There is no
conf.d/feeds/directory. Nothing creates one and no shipped package contains one. Feed configuration is the single file above. All feeds are disabled by default for safety — adding feed configuration is not sufficient to make feeds active;NFTBAN_FEEDS_ENABLEDmust also be true.
DDoS connection limits are NOT in config files. They are hardcoded in the
nftables schema generator (nft_schema.sh).
| Limit | Value | Location |
|---|---|---|
| SSH concurrent per IP | 15 | nftables schema (not configurable via conf.d) |
| HTTP concurrent per IP | 200 | nftables schema |
| Mail concurrent per IP | 30 | nftables schema |
| SYN rate (service ports) | 25/second burst 50 | nftables schema |
Changing these requires editing the schema generator and running
nftban firewall rebuild.
Every shipped configuration area, where it lives, and the key that turns it on. The files themselves carry a commented description above each key — this map exists so an area can be found, not to restate every key.
Paths are relative to /etc/nftban/. "Keys" is the number of settable keys shipped in
that file.
| Area | File | Master key | Default | Keys |
|---|---|---|---|---|
| Threat feeds | conf.d/feeds.conf |
NFTBAN_FEEDS_ENABLED |
false |
— |
| Metrics / export | conf.d/metrics.conf |
NFTBAN_METRICS_ENABLED |
false |
49 |
| Watchdog / pressure | conf.d/watchdog.conf |
NFTBAN_WATCHDOG_ENABLED |
true |
75 |
| Mail notifications | conf.d/mail.conf |
NFTBAN_MAIL_ENABLED |
NO |
24 |
| Log retention | conf.d/logs.conf |
LOG_RETENTION_MODE |
auto |
6 |
| Reports / statistics | conf.d/stats.conf |
STATS_ENABLED |
true |
24 |
| Trust providers (CDN/cloud allowlists) | conf.d/trust.conf |
TRUST_ENABLED |
true |
28 |
| Automatic updates | conf.d/update.conf |
NFTBAN_UPDATE_AUTO_ENABLED |
false |
12 |
| Zabbix export | conf.d/zabbix.conf |
NFTBAN_ZABBIX_ENABLED |
false |
32 |
| RBL monitoring | conf.d/rbl/main.conf |
NFTBAN_RBL_ENABLED |
NO |
18 |
| GeoIP database | conf.d/geoip/main.conf |
GEOIP_PROVIDER |
dbip |
13 |
| BotScan | conf.d/botscan/main.conf |
BOTSCAN_ENABLED |
true |
29 |
| Suricata interfaces | conf.d/suricata/interfaces.conf |
SURICATA_IFACE_MODE |
auto |
7 |
| DNS tunnel detection | conf.d/tunnel/main.conf |
NFTBAN_TUNNEL_ENABLED |
NO |
28 |
Also shipped: conf.d/ddos/, conf.d/portscan/, conf.d/login/, conf.d/botguard/,
conf.d/geoban/, conf.d/panels/ (per-panel), plus loose files for banner, connectors,
persistent state, login alerts, recovery, services and community stats.
Boolean spelling is not uniform across areas. Some files use true/false, others
YES/NO. Use the spelling already present in the file you are editing rather than
assuming.
Module enablement is parsed by a single canonical reader (nftban_bool_is_true), which
accepts, case-insensitively:
true · yes · 1 · on · enabled
Anything else — including a malformed or empty value — is false. Enablement never
fails open. Before this parser existed, NFTBAN_FEEDS_ENABLED was read three
incompatible ways and no single value satisfied every reader; YES and true each left
one consumer believing feeds were off.
Operator changes belong in .local files, which survive package upgrades:
conf.d/<area>/main.conf shipped defaults — may be replaced on upgrade
conf.d/<area>/main.conf.local your overrides — takes precedence
/etc/nftban/nftban.conf.local global operator overrides
conf.d/rbl/main.conf.local ships intentionally empty as an example of this pattern.
These appear in shipped configuration and in the config schema, but no code reads
them — setting one has no effect. Verified against origin/main: their only
occurrence in the tree is a declaration in config-schema.json.
| Key | File |
|---|---|
BOTSCAN_PROMETHEUS_ENABLED |
conf.d/botscan/main.conf |
BOTSCAN_GEOIP_ENABLED |
conf.d/botscan/main.conf |
BOTSCAN_ALERT_ENABLED |
conf.d/botscan/main.conf |
BOTSCAN_PATTERN_FILES |
conf.d/botscan/main.conf — the loader globs every *.patterns file instead |
NFTBAN_MAIL_DAILY_REPORT_TIME |
conf.d/mail.conf |
NFTBAN_MAIL_ALERT_SEVERITY |
conf.d/mail.conf |
For BotScan, alert-versus-ban behaviour is controlled by BOTSCAN_ACTION_MODE
(alert | ban | both), not by BOTSCAN_ALERT_ENABLED.
Two keys under conf.d/suricata/interfaces.conf — SURICATA_LAST_DETECTION and
SURICATA_LAST_CANDIDATES — are auto-populated by nftban suricata iface and are
informational; do not set them by hand.
Configuration affects the config axis of the health model. It does NOT directly affect structural, runtime, or effective axes.
| Config change | Config axis effect | Other axes effect |
|---|---|---|
Set ENABLED="true"
|
Config = ENABLED | None until enable command or rebuild |
Set ENABLED="false"
|
Config = DISABLED | None (kernel objects may persist as residual) |
| Change threshold | No axis change | Takes effect after next detection cycle |
| Add feed config file | Feeds = configured | Loaded after next feed sync |
| Remove feed config file | Feeds = DISABLED | Existing kernel data persists until rebuild |
The config axis is read-only from the health model's perspective. The validator compares config intent with kernel reality on the consistency axis.
# Check config intent
grep DDOS_ENABLED /etc/nftban/conf.d/ddos/main.conf.local
# Check kernel truth
nft list chain ip nftban ddos_protection
# Check validator interpretation
nftban validate --json | jq '.modules.ddos'
# Check consistency (config vs kernel agreement)
nftban validate --json | jq '.findings[] | select(.code == "VAL-CONS-001")'
# Findings = config says enabled but kernel objects missing
# Verify .local override precedence
cat /etc/nftban/conf.d/ddos/main.conf # base: DDOS_ENABLED="false"
cat /etc/nftban/conf.d/ddos/main.conf.local # override: DDOS_ENABLED="true"
nftban validate --json | jq '.modules.ddos.config'
# Expected: "enabled" (.local wins)-
Config does not control enforcement. Setting
ENABLED="true"does not create kernel objects. The operator must run the module enable command or rebuild the firewall. - Config changes require action to take effect. Most changes need a module reload, firewall rebuild, or daemon restart.
- DDoS connection limits are not in config. They are in the nftables schema generator. Changing them requires schema modification + rebuild.
-
Feeds have a master switch and it is off by default.
NFTBAN_FEEDS_ENABLEDin/etc/nftban/conf.d/feeds.confships"false". Feed sources are variables in that file, not files in a directory. - Config file permissions matter. If the validator or CLI cannot read a config file, the module defaults to DISABLED silently. No error is reported.
-
BotGuard thresholds are in kernel rules and config. The suspect rate/burst
values in
main.confare applied to kernel meter rules at rebuild time. Changing them in config without rebuilding has no kernel effect.
See also: Communications & Notifications (mail keys), Logging, Rotation & Retention, Audit Reports & Compliance, Maintenance & Scheduled Operations.
NFTBan Wiki
Getting Started
Architecture
- Architecture Overview
- Firewall Anchor Architecture
- NFT Schema & Validator Model
- Health & Validation
- Startup Lifecycle & Readiness
- Metrics & Evidence Model
- Watchdog & Resource Profiles
- Security Architecture
Protection & Monitoring
- Protection & Monitoring Modules
- BotGuard — HTTP Guard
- BotScan — HTTP Exploit Scanner
- DDoS Protection
- Portscan Detection
- Login Monitoring
- Blacklist & Threat Feeds
- Suricata IDS Integration
- RBL Monitoring
- DNS Tunnel Detection
Operator Reference
- CLI Commands Reference
- Configuration Reference
- Systemd Units & Timers
- Optimization & Tuning
- Security Operations Guide
- GeoIP Database Guide
- FHS Compliance
- Troubleshooting & Selftest
- Support Bundle & Incident Diagnostics
Operations, Communications & Reporting
- Maintenance & Scheduled Operations
- Logging, Rotation & Retention
- Communications & Notifications
- Notification & Report Templates
- Audit Reports & Compliance
Verification & Trust
Reference
Legal