PROTOCOLS-FUN . ATTACK & MITIGATION

Attack & Mitigation

Denial-of-service and bot attack classes from layer 3 to layer 7, and how each is mitigated.

Sort by what exhausts first (bandwidth / kernel table / CPU-backend), layer, and whether it looks like real traffic. Volumetric drowns the link; protocol/state exhausts finite tables (half-open conns, conntrack); application is cheap requests triggering expensive work; abuse is well-formed traffic you identify, not rate-drop.

the map
classlayerruns outexamples
VolumetricL3/4bandwidthUDP flood, amplification/reflection, ICMP flood
Protocol / stateL3/4a kernel tableSYN flood, ACK/RST flood, fragmentation, conntrack fill
ApplicationL7CPU / backendHTTP flood, Slowloris, HTTP/2 Rapid Reset, cache-bust
Bots & abuseL7your business logiccredential stuffing, scraping, scalping, AI crawlers
cost asymmetry. Higher layer = cheaper to send, costlier to serve: one crafted L7 request is a few bytes for the attacker and a DB query + template render + backend round-trip for the server. So L7/bot defense is identification, not out-muscling volume.

SYN flood: send the opening SYN, never complete the handshake; each pins a half-open-table slot until timeout. Amplification/reflection: small spoofed-source query to an open UDP service (DNS/NTP/memcached); the large reply lands on the spoofed victim.

a SYN segment - the half-open primitive

A real TCP SYN to port 443 (source/dest are RFC 5737 doc addresses). The whole attack is this one packet, sent by the million with spoofed sources so the SYN-ACKs go nowhere and the handshakes never finish.

SYN cookies. Store no half-open state; encode the connection into the SYN-ACK ISN (a MAC over the tuple + a slow timer). The client ACK returns it; the server recomputes and reconstructs the connection. Nothing to exhaust (RFC 4987).
a DNS amplification query - small in, huge out

A 36-byte ANY query with an EDNS0 option advertising a 4096-byte UDP buffer. Spoof the source to the victim and the multi-kilobyte answer is delivered to them, not you.

amplification factors (why UDP reflection scales)
serviceportbandwidth factor
DNS (ANY)53~28-54x
NTP (monlist)123~557x
SSDP1900~30x
CLDAP389~56-70x
memcached11211~10,000-51,000x
root cause: source spoofing. Reflection works only because the source IP is forgeable and the reflector answers anyone. BCP 38 / RFC 2827 edge ingress filtering (drop packets whose source can't come from that link) starves every amplification attack; not universally deployed.

Packets are valid HTTP; cost is server-side work. Floods hit uncached/expensive endpoints (search, login). Slow attacks (Slowloris, slow-read, slow-POST) pin worker threads/connections with a trickle of bytes, starving the pool at near-zero bandwidth. HTTP/2 multiplexing added a vector:

HTTP/2 Rapid Reset - a frame that cancels itself

The client opens a stream (HEADERS) then immediately cancels it with an RST_STREAM. The request is fully processed server-side but never counts against the max-concurrent-streams limit, so one connection can churn tens of thousands of requests/second. This is the RST_STREAM frame: a 9-byte HTTP/2 frame header + a 4-byte error code.

Rapid Reset (CVE-2023-44487, 2023). The largest L7 DDoS on record at the time - it exploited a spec-legal behavior, not a bug, so every HTTP/2 implementation was affected at once. Mitigation is counting resets and reused streams per connection and killing abusive ones, plus capping request rate independent of the stream-concurrency limit. Its cousin, the CONTINUATION flood (2024), abuses unbounded header CONTINUATION frames the same way.
slow attacks. Slowloris drops a thread-per-connection server from one laptop. Defense: event-driven servers, aggressive header/body timeouts, a reverse proxy that fully buffers the request before origin.

Well-formed, low-rate, distributed across residential proxy pools (real home IPs rented via malware/SDK networks), so IP reputation and rate limits barely dent it. Defense = distinguishing automated from human.

the abuse catalog
credential stuffingreplaying leaked user/pass pairs to find reuse -> account takeover (ATO)
cardingtesting stolen card numbers against a checkout, cents at a time
scrapingharvesting content/prices; now includes the surge of AI training crawlers
scalpingbots hoarding limited inventory (tickets, drops, GPUs) faster than humans
API abuseusing an API exactly as designed, just far too much / not as intended
AI crawlers. LLM training/retrieval bots scrape at soft-DDoS volumes: ignore robots.txt, rotate residential IPs, forge browser UAs. The clearest current case for fingerprint-based ID -- UA says "Chrome," the TLS/HTTP fingerprint says "Python library."

IP is unreliable (CGNAT, proxies, shared cloud) and the User-Agent is client-set free text. Fingerprint how the client speaks instead: TLS handshake shape, HTTP/2 settings, TCP options -- revealed by the library regardless of what it claims.

a JA4 fingerprint, decomposed

JA4 (the TLS ClientHello half of JA4+) hashes the negotiated capabilities into a stable, human-skimmable string. This is real Chrome:

t13d1516h2_8daaf6152771_02713d6af862
t13d1516h2the readable part: t=TCP, 13=TLS 1.3, d=SNI present, 15 cipher suites, 16 extensions, ALPN h2
8daaf6152771sha256[:12] of the sorted cipher-suite list
02713d6af862sha256[:12] of the sorted extensions + signature algorithms
JA4 vs JA3. JA3 hashed raw order-sensitive fields into one MD5 -- perturbed by GREASE + extension-shuffling, so a client could randomize its own fingerprint. JA4 sorts before hashing (defeats shuffling), strips GREASE, keeps a readable prefix -> stable + skimmable. JA4+ suite: JA4H (HTTP), JA4T/JA4TS (TCP), JA4S (ServerHello), JA4X (cert).
fingerprints spoof too. curl-impersonate / utls reproduce a real browser's ClientHello -- a match is strong evidence, not proof. State of the art combines fingerprint + behavior (timing, ordering, challenge-solving); no single signal is trusted alone.
capture it: pick these ClientHellos out of live traffic in capture & filter -- display filter tls.handshake.type == 1.

Stack cheap filters ahead of expensive ones so each layer sheds load first. Outside-in:

the layers
edge / networkAnycast spreads the load across many sites; scrubbing centers absorb volume; BGP flowspec + RTBH (remote-triggered blackhole) drop floods upstream; CDNs serve cached bytes so attacks never reach origin
transportSYN cookies, connection + rate caps, conntrack tuning - survive the state-exhaustion class
applicationWAF rules, rate limiting (token-bucket / sliding-window), challenges (JS, CAPTCHA, proof-of-work), fingerprint + reputation blocking, bot management
architecturalcache everything cacheable, degrade gracefully under load, tarpit + honeypot the obvious offenders, autoscale with a cost ceiling
proof-of-work challenges (Anubis, mCaptcha) make every client burn CPU-ms before service -- negligible per human, ruinous per bot at scale. Inverts the L7 asymmetry: the attacker pays per request.
rate limiting. Token-bucket allows bursts then throttles; sliding-window smooths; per-fingerprint / per-account beats per-IP against proxy pools. Honeypot endpoints/addresses (the ipv6-fun canary) turn any hit into a high-confidence hostile signal.

Attackers rent booter services by the hour and residential proxy pools of millions of real IPs. Defence needs anycast capacity, scrubbing contracts and engineering time, so it costs far more than the attack.

obscurity is not a control. Hiding an address/subdomain/fingerprint buys time and cuts noise, but anything discoverable is found and anything static is predicted. The controls are the ones you can reason about: rate, identity, challenge, capacity.
the loop doesn't converge. Better fingerprinting (JA4) -> better spoofing (uTLS) -> behavioral/multi-signal detection -> ... Durable posture: raise attacker cost + your observability faster than they adapt. Detect -> identify -> mitigate -> observe -> repeat.