zerohop.dev
ProThis module is part of zerohop Pro.

DDoS & Rate Limiting

Mitigation is usually ranked by throughput, and that is the wrong axis: no pinned tree publishes a packets-per-second capacity for XDP, tc, netfilter or an application limiter, because a ceiling like that depends on the NIC, the core count and the program. What the source does settle is the ORDER, and it settles it inside a single function — __netif_receive_skb_core() runs generic XDP and then the tc ingress hook forty lines apart, and the netfilter INPUT hook is not merely earlier than TCP but its caller, since ip_local_deliver() passes ip_local_deliver_finish as NF_HOOK's own continuation and that continuation is what dispatches to tcp_v4_rcv. So the question that decides whether a mitigation works is whether it runs before the resource the attack spends, and whether it can tell the attack apart from your traffic once it does. Both directions of that test get reversed in practice. An application-layer limiter cannot see a SYN flood at all, because limit_req is a PREACCESS-phase handler running after accept() and after a request line while a half-open connection dies in tcp_conn_request() — and a packet-rate drop cannot see an HTTP flood, because complete well-formed requests are the one shape a stage with no request state handles worst. The SYN queue is the most mis-tuned thing in the subject: the admission test compares against sk_max_ack_backlog, the value the application passed to listen() as clamped by somaxconn, while the sysctl everyone raises has exactly one reader in the kernel and it is skipped while syncookies are on. Cookies answer for that queue and nothing else, a completed handshake still dies on a full accept queue, and the cookie is not free — its payload is an index into a four-entry MSS table, so the connection's MSS is rounded down to one of four values. Amplification has a ceiling you can read rather than estimate: a query carrying no valid DNS COOKIE is answered into a buffer bounded by max-udp-size, 1232 bytes as shipped, with an absolute ceiling of 4096 because the send buffer is a fixed array — and a spoofed source can never reach the other branch, because the cookie is recomputed from the client's own address with the server's secret and compared. Slowloris is not a rate problem: 512 worker connection slots, released no sooner than a 60-second header timeout, means roughly nine new connections per second holds a worker, and a connection that has sent one byte is no longer reclaimable by nginx's own drain path. Two of the controls — anycast distribution and upstream scrubbing — have no pinned implementation, so the panel moves no number for either and says so. Change the attack, the rate, where the drop happens and the limiter algorithm, and watch the server-computed cascade across all five sections. Validated against Linux 6.12.93, nginx 1.30.5 and BIND 9.20.29 source.

  • All current + future modules
  • Full kata library
  • Progress dashboard + weak area analysis

Cancel anytime. Billed annually.

zerohop.dev — Interactive Network Protocol Simulators