Escalation ladders
A single mitigation method fires the same response the instant an attack is detected. An
escalation ladder instead steps the response up the longer an attack persists —
declaratively, with no callback scripts.
Most deployments are fine with a single mitigation: method. Reach for a ladder only when you
want a gentler response first (e.g. alert, then surgical filtering) before resorting to a full
blackhole.
escalation: # supersedes `mitigation` when present
- { after_seconds: 0, action: none } # alert only at first
- { after_seconds: 30, action: flowspec } # still under attack after 30s → surgical drop
- { after_seconds: 90, action: divert } # still under attack after 90s → scrub
- { after_seconds: 300, action: blackhole } # still under attack after 300s → blackhole
flowspec:
action: discard
scrubbing:
next_hop: "192.0.2.100" # scrubbing center; see Traffic diversion
community: "65000:200"
A bgp block is required for any rung to announce; the
flowspec and scrubbing blocks above are needed only for the flowspec and divert rungs.
How rungs apply
Each rung's after_seconds is measured from the attack's start. A rung applies once that
much time has elapsed and the ban is still active. (A ban is only withdrawn after traffic
has stayed below threshold for the configured cool-down period, ban.unban_hysteresis_seconds
— see Configuration.) The rung clock keeps running from the attack's
start throughout.
- The first rung must be at
0seconds. - A ladder may have at most 5 rungs — this is a hard limit; the daemon refuses to start with a longer ladder.
actionisnone(alert only),flowspec,divert(scrubbing), orblackhole.- A ladder may only hold or strengthen the response:
none<flowspec<divert<blackhole. De-escalating between rungs is a config error.
Make-before-break
Climbing to a rung is make-before-break: the new rung is announced first, and the previous one is withdrawn only after that succeeds — so the victim is never momentarily unprotected mid-switch. If the announce fails, the ban holds the working rung and retries on the next tick. If several rungs come due at once (a long-running attack, or the daemon catching up after a pause), the ban jumps straight to the highest due rung and never announces the rungs it skips.
A flowspec or divert rung whose announce the upstream peer rejects falls back to
blackhole (unless you set ban.fallback: none in Configuration); the
API and notifications surface this via the fell_back_from field. Blackhole and alert-only
rungs have no fallback.
The one exception to the announce-then-withdraw dance is divert → blackhole: both announce
the same host route (the victim's /32 or /128), so the blackhole announcement atomically
replaces the divert route — no separate withdraw, no gap. Cross-family switches (FlowSpec
rules vs. a host route) follow the make-before-break case above.
Lifecycle and compatibility
The ladder is per-hostgroup overridable and shares the rest of the ban lifecycle: TTL
auto-withdrawal, the max_active_bans cap, the blast-radius caps (max_banned_fraction,
max_bans_per_window), the absolute whitelist, and dry-run (which advances the ladder and
logs each rung but never announces).
When no escalation block is set, the single mitigation method behaves exactly as a
one-rung ladder at 0 seconds — full backward compatibility. Each ban in /api/v1/bans
exposes the full configured ladder (escalation), the index of the current rung
(escalation_step), and the active rung's method (method).
Related
- RTBH mitigation — the blackhole method.
- FlowSpec mitigation — the surgical method a ladder can step through.
- Traffic diversion — the
divertrung that scrubs instead of dropping. - Configuration reference · REST API
- Glossary — BGP, RTBH/blackhole, FlowSpec, host route and the other terms used here.