The site was slow, CPU was pinned, and our DDoS playbook had a clear first move: rank the IPs by hit count and block the loudest. So I ran it, looked at the top of the list, and found nothing worth blocking. The actual attacker was 55-plus unique IPs each hitting a single page once or twice, all from one hosting ASN, and the top-by-volume frame was blind to every one of them.
That gap cost real time during an active incident, with the site slow and CPU pinned while the ranking pointed me at nothing. What follows is the frame the playbook was missing.
The frame we had
Our standing tool walked the IIS log, grouped by source IP, sorted by hit count, and surfaced the top of the list. It works, and it has caught real bots. Earlier in this same incident it flagged AwarioBot, a brand-monitoring crawler, sitting at 1,643 hits from a single Hetzner IP. One noisy IP, one obvious line at the top, one cheap fix (a single user-agent block). That is the shape top-by-volume is built for: a concentrated bot.
The problem is that “concentrated” is an assumption baked into the ranking, not a property of attacks in general. When I ran the same analysis during this incident, the top of the list was full of legitimate traffic and recognizable crawlers. Nothing at the top was the cause. The cause was distributed across the long tail, where every individual IP looked like a single curious visitor.
What the swarm actually looked like
The attack signature was the inverse of what the tool ranks for. A single target URL (a roster/team page with query permutations) was being hit from a pool of 55-plus distinct source IPs, each one responsible for only one to three requests. Sorted by hit count, not one of those IPs cracked the list. Sorted by anything per-IP, they were noise.
The thing they shared was not request volume. It was origin. Nearly all of them traced back to the same hosting ASN, Alibaba Cloud, inside a documented hosting range for that provider. The signal was never in how loud any single IP was. It was in how many distinct IPs were aimed at the same page from the same network.
The axis that finds it
The fix to the analysis is to change the primary grouping. Instead of group-by-IP, rank-by-hits, the correct primary analysis for a suspected swarm is:
- group by URL plus query string,
- rank each URL by its count of unique source IPs,
- score each by what fraction of those IPs fall in known-bad ranges.
That flips the whole picture. A page being hammered by one IP and a page being fanned out across 55 IPs look identical under top-by-volume if the totals match, but they are completely different attacks. Unique-IP-count per URL separates them immediately. The roster page lighting up with dozens of one-shot IPs is a swarm. The same page hit hard by three IPs is something else.
The bad-range percentage is the second axis, and it is what keeps you from overreacting. Tournament days produce real traffic spikes, and a page can show a high unique-IP-count for entirely legitimate reasons. Scoring each suspect URL by the share of its source IPs that already sit in flagged ranges is what lets you call swarm versus mixed versus organic without blocking real customers on the busiest day of their season. The verdict is a function of two numbers (bad-percentage and unique-IP-count), not one.
The block, and the proof
Once the swarm was identified by its ASN rather than by any individual IP, the mitigation was a single Windows Firewall rule against the Alibaba Cloud range:
New-NetFirewallRule -Direction Inbound -Action Block -RemoteAddress <hosting-range> ...CPU dropped from 73% to 11% and current connections from roughly 1000 to 128, in seconds. The reason it was that cheap is worth noting: a TCP-dropped packet at the firewall costs the IIS layer nothing, whereas an app-layer block still runs the request through the worker process to issue a redirect. For a distributed swarm hitting from a single network, the firewall is both the right layer and the cheap one.
It does not hold still
Blocking the range did not end it. Within hours the swarm rotated to a different documented /10 inside the same ASN. Alibaba Cloud owns far more address space than what our IP-ranges data had ever flagged, so our internal list was a stale subset of the real allocation. The lesson there is to block from the actual public whois allocations (ARIN, RIPE, APNIC), not from your own historical data.
And the counter-caution that keeps this from becoming a footgun: the same broader space includes carrier mobile ranges (Bell Mobility Canada, AT&T Mobility). A lazy wide block across that broader space would have taken out real customers on their phones. ASN-level blocking is a moving target in both directions. The attacker rotates into ranges you do not know about, and the ASN owns ranges you must never touch. So every rule got a dated, named convention so that querying the firewall rules reconstructs the block history later and ties each block back to an incident.
Match the tool to the attacker shape
Bot mitigation is a tiered decision, and picking the wrong tier is how you either miss the attack or block real users:
- A single named crawler hammering every sort permutation of a page (AwarioBot was the example) gets one line in the user-agent blocklist. Cheap, source-agnostic, and correct, because it is identified and not rotating.
- A single aggressive IP gets an IP-level block.
- A distributed swarm gets a firewall CIDR block scoped to the ASN, because the user-agent is generic or rotating and the per-IP volume is too low to catch.
Top-by-volume is the tool for the first two. It is structurally blind to the third, and the third is the one that actually pinned the box.
The takeaway
Next time CPU spikes and the top-IP list looks clean, group by full URL plus query string and rank each one by its count of unique source IPs. Check what share of those IPs sit in a known-bad range before you call it a swarm, and before you write any CIDR block, confirm the range doesn’t overlap a carrier or mobile allocation. That’s the check that finds the fan-out and keeps you from taking out real customers on their phones.
Related
- Bot Swarm Detection: The Three-Signal Triangle That Catches What IP Reputation Misses: the three-signal framework that confirms a swarm once the fan-out is visible
- Operator, not IP: fingerprinting a 40,000-IP proxy swarm by its RIPE maintainer: going further upstream to fingerprint the operator, not just the netblock
- One ASN to block them all, and the regional-ISP red herring that almost over-blocked: how a single netblock rule can collapse a swarm, and where it can overreach
- The 3% bot attack that took the site down: why your IP blacklist can’t see residential proxies: a residential-proxy variant where the swarm hides behind even more legitimate-looking IPs
- Whack-a-ASN: the scraper rotates /10s faster than you can whois: what happens after a CIDR block lands and the attacker rotates to the next range