-
Notifications
You must be signed in to change notification settings - Fork 0
DDoS Protection
Type: Module Layer: L1 — Traffic pressure (L3/L4) Since: v1.80.x Config:
conf.d/ddos/main.conf(.localoverride) Daemon dependency: NO — kernel-only enforcement Last verified: v1.218.7
See also: Glossary | Health Model | Architecture | Known Limitations
DDoS protection is a L3/L4 module that filters malformed packets, enforces per-IP connection limits, applies SYN rate limiting, and implements a graduated penalty ladder for repeat offenders. All enforcement is kernel-only via nftables rules — the daemon is not required for packet-level protection.
DDoS protection operates through four helper chains in the nftables input pipeline. Each chain handles a distinct class of traffic pressure:
| Chain | Pipeline Phase | Purpose |
|---|---|---|
ddos_sanity |
Phase 1 (Hygiene) | Drops malformed packets (Xmas, NULL, non-SYN new, fragmented) |
ddos_penalty |
Phase 3 (Ban) | Graduated penalty ladder for IPs in penalty sets |
ddos_prefix |
Phase 5 (Detect) | Per /24 prefix SYN and connection rate limiting (IPv4). Per /64 prefix in IPv6. |
ddos_protection |
Phase 5 (Detect) | Per-IP connection limits for SMTP, DNS, ICMP, UDP. Rate limiting. |
The kernel evaluates an inbound packet against the chains in order; the first
matching guard drops it, otherwise it proceeds to service admission. The
thresholds shown are the shipped defaults (conf.d/ddos/classic.conf,
per-host configurable). As of v1.197.0:
flowchart TD
P([Inbound packet]) --> S{ddos_sanity<br/>Phase 1 hygiene}
S -- "Xmas / NULL / non-SYN-new / fragmented" --> D1[DROP]
S -- clean --> PEN{ddos_penalty<br/>Phase 3 ban ladder}
PEN -- "source in ban set" --> D2[DROP]
PEN -- "in rate-limit set, over limit" --> D3[DROP]
PEN -- "within limit / not penalised" --> CT{Per-IP connection limits<br/>ct count · Phase 5}
CT -- "SSH > 15 concurrent" --> D4[DROP]
CT -- "HTTP/HTTPS > 200 concurrent" --> D5[DROP]
CT -- "Mail/SMTP > 30 concurrent" --> D6[DROP]
CT -- "within limits" --> SYN{per-IP service-port<br/>SYN meter · 25/s burst 50}
SYN -- "over rate" --> D7[DROP]
SYN -- "within rate" --> PFX{ddos_prefix SYN/conn<br/>/24 IPv4 · /64 IPv6 · 100/s burst 200}
PFX -- "prefix SYN/conn flood" --> D8[DROP]
PFX -- "ok" --> PROT{ddos_protection<br/>SMTP/DNS/ICMP/UDP flood}
PROT -- "service flood" --> D9[DROP]
PROT -- "ok" --> ADM([Service admission · Phase 6])
The textual Traffic flow below is the precise per-rule reference; the diagram
is a navigational overview of the same path. Enforcement is kernel-only — see
Kernel-only enforcement.
Packet arrives at input chain
│
├── Phase 1: jump ddos_sanity
│ Xmas/NULL/non-SYN-new/frag → DROP
│ Clean → return to input chain
│
├── Phase 3: jump ddos_penalty
│ IP in ban set → DROP
│ IP in rate-limit set + exceeds limit → DROP
│ IP in rate-limit set + within limit → return
│ IP not in penalty sets → return
│
├── Phase 5: (after established/ICMP accept)
│ SSH: > 15 concurrent per IP → DROP (input_ct_ssh_drop)
│ HTTP: > 200 concurrent per IP → DROP (input_ct_http_drop)
│ Mail: > 30 concurrent per IP → DROP (input_ct_mail_drop)
│ SYN to service port: rate meter → ACCEPT or DROP (input_syn_rate_exceeded)
│ jump ddos_prefix → /24 SYN + conn rate limiting
│ jump ddos_protection → SMTP/DNS/ICMP/UDP flood protection
│
▼
Continue to service admission (Phase 6)
Once rules are loaded, DDoS protection works without the daemon. If nftband
stops, all rate limits, connection limits, and penalty rules continue enforcing.
The penalty ladder is scored by the shell maintenance timer
(nftban_ddos_classic.sh); the daemon only proxies the resulting set-write
through its single nftables-write authority (IPC) and does not perform the
scoring itself. Schema generation and reload are handled by the CLI.
Packet-level decisions are entirely kernel-side.
This is fundamentally different from BotGuard and LoginMon, which require the daemon for scoring and set population.
| Chain | Rules (typical) | Purpose |
|---|---|---|
ddos_sanity |
5 | Malformed packet filtering |
ddos_penalty |
6 | Graduated penalty ladder (ban/drop/rate-limit tiers) |
ddos_prefix |
4 | Per-prefix SYN and connection flood protection |
ddos_protection |
8 | Per-service connection limits and flood protection |
Each chain must have > 0 rules. A chain with 0 rules is DEGRADED (B80-3).
| Counter | Family | Evidence | Meaning |
|---|---|---|---|
input_ct_ssh_drop |
ip + ip6 | ENFORCEMENT | SSH per-IP connection limit exceeded (> 15 concurrent) |
input_ct_http_drop |
ip + ip6 | ENFORCEMENT | HTTP per-IP connection limit exceeded (> 200 concurrent) |
input_ct_mail_drop |
ip + ip6 | ENFORCEMENT | Mail per-IP connection limit exceeded (> 30 concurrent) |
input_syn_rate_exceeded |
ip + ip6 | ENFORCEMENT | SYN rate exceeded or non-service port SYN |
input_syn_prefix_drop |
ip6 only | ENFORCEMENT | IPv6 /64 prefix SYN rate exceeded (anti-rotation) |
Each counter maps to exactly one enforcement decision. Unlike the shared blacklist counter, DDoS counters are independently attributable.
Counter > 0 = ENFORCING (positive evidence). Counter = 0 = NEUTRAL (not failure).
Where the connection-limit counters live. The
input_ct_ssh_drop,input_ct_http_drop, andinput_ct_mail_dropcounters are part of the always-on base schema (rendered into the input chain at install), not the DDoS module. They enforce per-IP connection limits (SSH 15, HTTP/HTTPS 200, Mail 30) even whenDDOS_ENABLED="false". They are listed here because they sit in the same input pipeline the DDoS chains feed into, but they do not depend on DDoS being enabled.
| Set | Purpose |
|---|---|
ddos_ban_1h |
IPs banned for 1 hour (repeat offenders) |
ddos_drop_5m |
IPs dropped for 5 minutes |
ddos_limit_5m |
IPs rate-limited for 5 minutes |
ddos_limit_10s |
IPs rate-limited for 10 seconds |
Penalty sets are timeout-based. The penalty ladder is computed by the shell
maintenance timer (nftban_ddos_classic.sh), which scores strikes and selects
the target penalty set. The daemon only proxies the resulting set-write through
its single nftables-write authority (IPC); it does not perform the scoring.
Existing penalty entries keep enforcing via kernel timeouts if the daemon stops.
| Meter | Purpose |
|---|---|
syn_meter_v4 / syn_meter_v6
|
Per-IP SYN rate tracking for service ports |
ddos_prefix_syn |
Per /24 prefix SYN rate |
ddos_prefix_conn |
Per /24 prefix connection rate |
ddos_dns_udp |
Per-IP DNS/UDP rate |
ddos_icmp_flood |
Per-IP ICMP rate |
ddos_udp_flood |
Per-IP UDP rate |
Meters are nftables dynamic sets, not named counters. They do not provide
direct evidence. Enforcement from meter-triggered rules must be inferred
from the associated drop counters (e.g., input_syn_rate_exceeded).
| Key | File | Default | Meaning |
|---|---|---|---|
DDOS_ENABLED |
conf.d/ddos/main.conf |
"false" |
Master enable/disable |
DDOS_MODE |
conf.d/ddos/main.conf |
"auto" |
Mode: auto, classic, hybrid
|
Override via main.conf.local (survives upgrades).
| Service | Limit | Counter |
|---|---|---|
| SSH (port 22) | 15 concurrent per IP | input_ct_ssh_drop |
| HTTP/HTTPS (ports 80, 443) | 200 concurrent per IP | input_ct_http_drop |
| Mail (ports 25, 465, 587) | 30 concurrent per IP | input_ct_mail_drop |
| SYN rate (service ports) | 25/second burst 50 | input_syn_rate_exceeded |
These limits are set in the nftables schema at rebuild time. Changing them
requires a schema rebuild (nftban firewall rebuild).
This module follows the 4-axis model:
- Config: ENABLED / DISABLED
- Structural: PRESENT / MISSING (4 chains exist + jump rules in input chain)
- Runtime: Always PASS (kernel-only module — daemon not required for enforcement)
- Effective: ENFORCING (any DDoS counter > 0) / IDLE (all counters = 0, NEUTRAL)
| Config | Structural | Runtime | Effective | System Contribution |
|---|---|---|---|---|
| DISABLED | — | — | — | skip |
| DISABLED | PRESENT (residual) | PASS | ENFORCING | informational (kernel still enforcing) |
| ENABLED | PRESENT (chains exist) | PASS | ENFORCING | PROTECTED |
| ENABLED | PRESENT (chains exist) | PASS | IDLE | IDLE |
| ENABLED | PRESENT (chains exist, rules = 0) | PASS | — | DEGRADED (empty chain, B80-3) |
| ENABLED | MISSING | PASS | — | DEGRADED |
When DDoS is DISABLED in config but chains persist in kernel from a prior enable, traffic is still being rate-limited and connection-limited. This is a valid operational state — config lags kernel reality. The validator reports this as informational, not DEGRADED.
To remove residual chains: nftban firewall rebuild (regenerates schema
without DDoS chains when DISABLED).
nftban ddos status # Show DDoS module state
nftban ddos enable # Enable DDoS protection
nftban ddos disable # Disable DDoS protection
nftban ddos show # Show current rules and counters# Check if chains exist (structural)
nft list chain ip nftban ddos_sanity
nft list chain ip nftban ddos_protection
# Expected: chain with rules. Empty chain = DEGRADED.
# Check enforcement counters
nft list counter ip nftban input_ct_ssh_drop
nft list counter ip nftban input_ct_http_drop
nft list counter ip nftban input_syn_rate_exceeded
# Counter > 0 = ENFORCING. Counter = 0 = NEUTRAL (not failure).
# Check module state via validator
nftban-validate --json | jq '.modules.ddos'
# Expected: {"config":"enabled","structural":"present","effective":"enforcing"}
# or effective:"idle" if all counters are zero
# Verify chain has rules (not empty)
nft list chain ip nftban ddos_protection | grep -c "comment"
# Expected: > 0. Zero = DEGRADED (B80-3).
# Check residual state (when disabled)
nft list chains ip nftban | grep ddos
# If chains exist while DDOS_ENABLED="false" → valid residualSymptom: Validator reports structural: "missing" for DDoS.
Cause: Module enabled in config but chains not loaded in kernel.
Fix: nftban ddos enable or nftban firewall rebuild
Symptom: Finding VAL-CHAIN-004 for a DDoS chain.
Cause: Failed enable or partial rebuild.
Fix: nftban ddos enable
Symptom: All DDoS counters show 0 packets after days of uptime. Meaning: NEUTRAL — no traffic has exceeded the configured limits. This is valid behavior on a low-traffic or well-configured host. It does NOT mean the module is broken.
All named counters reset to 0 after nftban firewall rebuild. Zero counters
immediately after rebuild = NEUTRAL (expected), not evidence of failure.
Anchor counters will begin incrementing as traffic flows; enforcement counters
will increment when limits are exceeded.
-
No per-chain packet counter. Individual chain traversal (how many packets
entered
ddos_sanityvsddos_protection) is not measurable. Only the named enforcement counters are queryable. - Connection limits are in the schema, not config. Changing SSH/HTTP/Mail connection limits requires editing the schema generator and rebuilding. There is no runtime config variable for these limits.
-
New penalty escalations pause without the write path. The penalty ladder
is scored by the shell maintenance timer (
nftban_ddos_classic.sh), but the resulting set-write is proxied through the daemon's single nftables-write authority (IPC). Kernel enforcement of existing penalty entries continues regardless; adding new IPs to penalty sets needs both the timer and that write path. Existing entries keep enforcing via kernel timeouts if the daemon stops. -
SYN meter and DDoS counters overlap.
input_syn_rate_exceededfires both for legitimate SYN floods AND for SYN to non-service ports. It proves enforcement occurred, not that an attack was blocked. -
IPv6 prefix counter is separate.
input_syn_prefix_drop(IPv6 only) tracks /64 prefix SYN rate violations. This counter is checked by the validator alongside IPv4 counters.
NFTBan Wiki
Getting Started
Architecture
- Architecture Overview
- Firewall Anchor Architecture
- NFT Schema & Validator Model
- Health & Validation
- 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
Operations, Communications & Reporting
- Maintenance & Scheduled Operations
- Logging, Rotation & Retention
- Communications & Notifications
- Notification & Report Templates
- Audit Reports & Compliance
Verification & Trust
Reference
Legal