From throttling to banning

Free preview 4 min to read

The previous course ended with a working set of throttles: sign-in limited by address and by account, signup and password reset bounded, a general volume limit. Against a script that hammers as fast as it can, that is enough.

Against a script that reads the response, it is not.

The gap

A throttle has a period, and a period is a promise. Ten attempts per minute means an attacker who waits gets ten more:

12:00:00   10 attempts   →  10 allowed, then 429
12:01:00   10 attempts   →  10 allowed, then 429
12:02:00   10 attempts   →  10 allowed, then 429
...
14,400 attempts a day, from one address, entirely within your limits

Nothing is broken. The limiter is doing what you configured, and the attacker is doing what the limiter permits. Fourteen thousand credential-stuffing attempts a day is a real attack conducted politely.

The missing piece is memory. A throttle knows about the current window and nothing else. So a client that behaves badly, waits, and behaves badly again looks like two unrelated clients that each behaved badly once.

Banning is a throttle with a longer arm

flowchart LR
  R["Requests"] --> T["Throttle: is this window over the limit?"]
  T -->|"yes"| N["429 — resets next window"]
  T --> F["Fail2Ban: has this client misbehaved N times in findtime?"]
  F -->|"yes"| B["Blocked for bantime — every request, not just the excess"]
  B --> E["Expires on its own"]

Three numbers describe it, and they are the vocabulary for the rest of this course:

Parameter Means
maxretry How many failures before blocking
findtime The window those failures must fall within
bantime How long the block lasts

"Three failures in ten minutes, blocked for an hour" is a sentence with a different shape from "ten requests per minute". It carries memory across windows, and it refuses everything from that client rather than only the excess.

When escalation is right

Not always, and being clear about this prevents the most common mistake in this course:

Right for unambiguous signals. A request for /etc/passwd, a probe for /.env, a sign-in with an email that does not exist attempted forty times. No legitimate client does these, so a false positive is nearly impossible.

Wrong for ambiguous ones. A user who forgot their password and tried six times, a mobile client retrying on a flaky connection, an office where four people signed in at once. Banning here produces a support ticket and a person who cannot use your product.

The asymmetry is the whole design principle: the cost of a false positive is much higher than the cost of a false negative. A missed attacker tries again and is caught by the next signal; a blocked customer leaves. Every threshold in this course should be set with that ratio in mind. And it argues for banning on kind of behavior rather than on volume of it.

What a ban is not

  • Not permanent. A ban with no expiry is a support queue you have created, and lesson 3 develops why.
  • Not identity. You are blocking an address or a key, not a person. The person moves; the address is reassigned to someone innocent.
  • Not a deterrent. Nobody is discouraged. It raises cost, which is the same honest framing as the previous course.
  • Not free of collateral. Blocking a shared address blocks everyone behind it, which is the coarse-discriminator problem escalated.

What this course covers

  1. From throttling to banning (this lesson).
  2. Fail2Ban and Allow2Ban.
  3. Escalation and backoff.
  4. Signals beyond the count.
  5. The edge, and what your application should not do.
  6. Abuse response and operations.
  7. Putting it together: a layered defense.

Key takeaways

  • A throttle has no memory across windows, so a patient attacker gets its full budget every period, indefinitely.
  • Banning adds memory: maxretry failures within findtime blocks a client for bantime.
  • A ban refuses everything from that client, including requests under the limit.
  • Escalate on unambiguous signals; ambiguous ones produce support tickets and lost customers.
  • A false positive costs far more than a false negative, and every threshold should reflect that.
Lesson 1 of 7 · free

Keep going with lesson 2

Fail2Ban and Allow2Ban

How Fail2Ban counts suspicious requests, Allow2Ban counts every matching request, and why ban keys need a namespace.

A free account also gives you the quizzes, your progress and notes, and the discussion.

Type to start searching...