Carpet bombing: staying under every limit at once

Carpet bombing splits an attack across many addresses so that no single one receives enough traffic to cross a threshold. The total is overwhelming and every individual measurement looks ordinary, which is the point: defences that decide per address, per source, or per endpoint have nothing to react to, because each of those views is below the line.

Section Attacks Updated Forms two

Quick facts

Layer
Classically network (3); the same principle appears at layer 7
Vector
Traffic spread thinly across many targets or many sources
Goal
Exceed capacity in aggregate while staying under every per-entity limit
In your logs
Often nothing unusual, because your address is only one of many
Does a WAF stop it?
Partly. It sees the application-layer form through aggregate analysis; the network form is not visible to it at all

That last row deserves the honesty. The classic version of this technique is a network-layer problem, and a page filed under application attacks should say so rather than imply that request inspection answers it.

The principle

Nearly every automatic defence is a threshold attached to an entity: this many requests from one client, this much traffic to one address, this many errors on one endpoint. The entity is what makes the rule practical, since a limit has to apply to something.

Distribution attacks the entity, not the limit. If a hundred addresses each receive a modest share, every per-address view is unremarkable while the link carrying all of them is not. Nothing needs to be hidden, and no technique needs to be clever: the traffic is simply arranged so that the question your defences ask returns a reassuring answer.

EVERY VIEW IS UNDER THE LINE — THE SUM IS NOT THRESHOLD PER SOURCE — EVERY ONE UNREMARKABLE IN AGGREGATE // nothing needs to be hidden and no technique needs to be clever // the question your defences ask returns a reassuring answer
// distribution attacks the entity, not the limit

Two forms of the same idea

Spread across destinations. The classic version, aimed at whoever carries traffic for a range of addresses. Each address in the range gets too little to trigger anything, while the router or link serving the range saturates. The victim is the infrastructure rather than any single site, and the operators of the individual sites may see nothing at all until their connectivity fails.

Spread across sources and paths. The application-layer analogue: many sources, each making few requests, distributed across endpoints so that no path and no client stands out. Per-client rate limits are blind by construction, since the design assumption behind them is that abuse concentrates somewhere.

The second form is where request inspection can help, and only when it is looking at totals rather than at individuals.

Why thresholds are blind here

Three reasons, and they are structural rather than a matter of tuning.

A threshold needs a subject. Whatever you count, you count it per something, and the technique arranges for that something to look normal. Lowering the threshold does not fix this; it produces false positives long before it catches a distributed sender.

Averages hide it. A total that is unremarkable for the whole system can be composed of many small anomalies, and averaging is the operation that removes them from view.

The evidence may not be yours. In the network form, the only party who can see the aggregate is the one carrying the whole range. Your own logs are a slice too small to contain the pattern, which is why an operator can truthfully report that nothing is wrong with their site while being part of an event.

THE PATTERN EXISTS ONLY IN A VIEW YOU DO NOT HAVE A RANGE OF ADDRESSES, EACH GETTING TOO LITTLE TO TRIGGER ANYTHING YOUR LOGS — THIS SLICE, AND IT LOOKS NORMAL WHAT THE CARRIER SEES — THE ONLY VIEW THAT CONTAINS THE PATTERN // no amount of work on your own systems reconstructs it // the information was never in your logs to begin with
// an operator can truthfully report nothing is wrong while being part of an event

What actually sees it

Detection has to change subject: from entities to totals, and from absolute values to deviations.

Aggregate baselines. Total requests, total connections, and total traffic compared against what is normal for the time of day and day of week. A pattern invisible per client is often obvious in the total.

Cross-endpoint correlation. Many endpoints each slightly busier than usual, at the same time, from populations with nothing in common. Each alone is noise; together they are a shape.

Population novelty. A large number of sources that have no history is a stronger signal than any of them individually exceeding a limit.

The general approach behind these belongs to how limits are designed and is covered where rate limiting is discussed in full, not here.

Mitigation by layer

Four measures, and the first is a phone call rather than a configuration change.

Ask whoever carries your traffic what the aggregate looks like. In the network form this is not optional: they hold the only view that contains the pattern, and they can filter at a level you cannot reach.

Limit on totals as well as on individuals. A ceiling on concurrent work for an endpoint, independent of who is asking, catches distributed load that per-client limits miss.

Price requests rather than count them. Where the cost of serving a request is what matters, a budget expressed in work instead of requests is harder to spread under, because the total cost is the thing being constrained.

Prefer challenges to blocks at low confidence. With distributed traffic, confidence about any individual source is low by construction, so measures that ask rather than refuse cost less when they land on a customer.

What does not help on its own: per-source rate limits, address blocking, and lowering thresholds. The first two are the mechanism being defeated, and the third trades a missed attack for refused customers.

The trade-off in aggregate limits

This is the cost of the main recommendation above.

A limit on totals cannot tell which contributor to refuse. When it engages, it applies to whoever arrives next, which includes customers, and it does so precisely during the busiest moments, since that is when totals are highest. A genuine surge and a distributed attack look the same to a counter that only knows the total.

That is why aggregate ceilings work best as protection against collapse rather than as everyday enforcement: set where the system would fail anyway, they trade a degraded experience for an outage. Set close to normal traffic, they become an outage of their own.

Where the platform sits

Bridge WAF inspects requests before they reach your origin and applies rate limiting per domain, which addresses the application-layer form when combined with attention to totals rather than to individual sources. The network form, where traffic is spread across a range of addresses to saturate the infrastructure carrying them, is not something request inspection can see, and it belongs with whoever provides that connectivity. See what the platform offers at Bridge CDN.

Questions

What is carpet bombing in a DDoS context?

Traffic spread deliberately across many addresses or sources so that no single one of them ever crosses a detection threshold, while the sum comfortably exceeds what the target can carry. It defeats the measurement rather than the capacity, which is why it survives defences that work against concentrated traffic.

Why do rate limits not catch it?

Because a limit applies to one entity at a time, and the traffic is arranged so that every individual entity looks entirely ordinary. The pattern exists only in the sum, and a mechanism that examines clients one at a time has no way to see a sum.

Can I see it in my own logs?

Frequently not. In the network form the traffic is spread across a whole range of addresses, so the pattern exists only in an aggregate held by whoever carries traffic for that range. Your logs contain your slice, and your slice looks normal.

Does a WAF stop it?

Partly, and the split matters. The application-layer form is visible if you analyse traffic in aggregate rather than per client, which request inspection can do. The network form never becomes requests at all and is therefore outside its reach entirely.

Should I lower my thresholds?

That is the instinctive response and it fails in a specific way: it starts refusing genuine customers long before it approaches traffic engineered to sit beneath any threshold. Change what you measure, moving to aggregates, rather than how strictly you measure the same thing.

What is the single most useful step?

Asking whoever carries your connectivity what the aggregate looks like. They hold the only view in which this pattern is visible, and no amount of work on your own systems reconstructs it, because the information was never in your logs to begin with.

Where the platform sits

The application-layer form, and only with attention to totals. The network form belongs to whoever carries your traffic.

off

No request is inspected and no total is counted.

monitor

What a limit would have refused is recorded, which is where a distributed shape first becomes readable.

block

Refusal applies at the edge, per domain, and every refusal is recorded with it.

The firewall layer is included with Bridge CDN. Start in monitor: nothing is refused until you decide it should be.

Get started