A Field Guide to Denial-of-Service Attacks
A denial-of-service attack has one goal — make a service unavailable — and a dozen ways to reach it, operating at different layers with wildly different economics. Understanding the taxonomy matters because the defenses don't transfer: what stops a volumetric flood does nothing against a slow application-layer attack, and vice versa. Here's the map, current through the attacks defining 2026.
Three families by what they exhaust
1. Volumetric — exhaust the pipe
Fill the target's bandwidth so legitimate packets can't get through. The math favors the attacker through reflection and amplification: send a small spoofed query to a third-party server that answers a much larger response to the victim.
- DNS amplification — a tiny query yields a large response; classic and still common.
- NTP, memcached, CLDAP reflection — memcached's amplification factor made possible the record-setting 1.3 Tbps GitHub attack of 2018.
- Carpet bombing — spreading the flood across an entire subnet to slip under per-IP thresholds.
2. Protocol/state — exhaust the connection table
Consume finite per-connection resources rather than bandwidth.
- SYN flood — half-open TCP handshakes with spoofed sources fill the backlog. Defended by SYN cookies, which encode connection state in the sequence number so no memory is committed until the handshake completes.
- ACK/RST floods, fragmentation attacks — force expensive packet processing.
3. Application-layer (Layer 7) — exhaust the app
Low-bandwidth, high-impact: mimic legitimate requests that are cheap to send and expensive to serve.
- HTTP flood — a botnet requests expensive endpoints (search, checkout) that hit databases.
- Slowloris — hold many connections open by sending headers one byte at a time; a single machine can stall a naive server.
- HTTP/2 Rapid Reset — the defining L7 attack of recent years, abusing HTTP/2 stream multiplexing by opening and instantly cancelling streams, forcing enormous server work from modest client effort. Every major CDN patched it; the lesson — new protocols bring new DoS surface — is permanent.
The mitigation stack
| Attack family | Primary defense |
|---|---|
| Volumetric | Upstream scrubbing / anycast CDN with capacity far exceeding any botnet; BGP flowspec to drop at the edge |
| Protocol/state | SYN cookies, connection rate limits, stateful firewall tuning |
| Application-layer | WAF, per-client rate limiting, bot management, request-cost budgeting, up-to-date protocol stacks |
The strategic point: absorbing volumetric attacks requires more capacity than the attacker can muster, which for most organizations means a cloud scrubbing provider or anycast CDN — you cannot out-bandwidth a global botnet from a single data center. Layer 7 is the opposite: the fight is about telling human from bot cheaply, per request.
Defensive rate limiting, done right
Naive rate limits punish shared-NAT users and miss distributed attacks. A token-bucket limiter keyed on a real identity signal, with graceful backpressure, is the workhorse — here in Lua for an edge proxy:
-- Token bucket per client key (e.g., API key, or IP+ASN for anonymous)
-- Backed by shared memory / Redis; returns true if the request may proceed.
local function allow(key, rate, burst)
local now = ngx.now()
local b = bucket_store:get(key) or { tokens = burst, ts = now }
-- Refill based on elapsed time, capped at burst
b.tokens = math.min(burst, b.tokens + (now - b.ts) * rate)
b.ts = now
if b.tokens < 1 then
bucket_store:set(key, b, 60)
return false -- 429 Too Many Requests
end
b.tokens = b.tokens - 1
bucket_store:set(key, b, 60)
return true
end
-- Prefer a stable identity over raw IP; fall back thoughtfully
local key = ngx.var.http_x_api_key
or (ngx.var.remote_addr .. ":" .. (ngx.var.asn or "0"))
if not allow(key, 10, 40) then -- 10 req/s sustained, burst 40
return ngx.exit(429)
end
Combine it with connection-level timeouts (kill Slowloris), a WAF for signatures, and — critically — a runbook that shifts you behind scrubbing when volumetric traffic exceeds your local capacity. During an attack is the wrong time to read the CDN's onboarding docs.
Before the attack
- Know your baseline traffic, so anomalies are visible.
- Have scrubbing/CDN pre-provisioned and tested — failover you've never exercised will fail.
- Rate-limit and set timeouts by default, not as an incident response.
- Keep protocol stacks patched; new features (HTTP/2, HTTP/3/QUIC) ship new DoS surface.
DoS is a resource-exhaustion problem in disguise. Identify which resource each attack drains — pipe, connection table, or application — and defend that specific one; there is no single shield.