Skip to content

DoS / DDoS attacks

An IDS or IPS, from the previous article, is built to notice traffic that's carrying something malicious — an exploit payload, a scan pattern, a brute-force attempt. A denial-of-service attack doesn't need to sneak anything past that kind of inspection at all. Every single request can look completely ordinary on its own; the attack is simply sending far more of them, or far larger ones, than the target was ever provisioned to handle. NIST's own glossary defines the underlying concept plainly: denial of service is "the prevention of authorized access to resources or the delaying of time-critical operations." Nothing in that definition mentions exploiting a bug — making a service unavailable is the entire goal, and volume alone is often enough to achieve it.

DoS versus DDoS: one attacker or an army of them

A denial-of-service (DoS) attack comes from a single source — one machine, one connection, one attacker's own bandwidth. That ceiling is also the natural limit on how much damage it can do: a single home internet connection generating traffic as fast as it can still tops out at whatever bandwidth that one connection has, which is rarely enough to meaningfully affect a well-provisioned server or service on its own.

A distributed denial-of-service (DDoS) attack removes that ceiling by using many machines at once, all directed at the same target simultaneously. The most common source of that many-machines scale is a botnet — a large collection of compromised devices (often poorly secured IoT devices, routers, or infected computers) that an attacker controls remotely and can direct to send traffic on command, without the owner of any individual device ever knowing their hardware is participating. A botnet numbering in the tens or hundreds of thousands of devices, each contributing even a modest amount of bandwidth, adds up to an aggregate flood far beyond what any single-source DoS attack could ever produce — and because the traffic arrives from thousands of genuinely distinct source addresses scattered across the internet, blocking "the attacker's IP" isn't a coherent response the way it would be against a lone attacker.

A DoS attack is one firehose; a DDoS attack is thousands of garden hoses pointed at the same target, all turned on at once.

Three shapes a DDoS attack takes

Not every flood works the same way, and the three broad categories below target different resources — bandwidth, server-side connection state, and application logic — which is also why they need different defenses.

Volumetric attacks aim to saturate the target's network bandwidth itself, so that legitimate traffic simply can't get through the pipe regardless of how well the server behind it is provisioned. The classic technique here is reflection and amplification: an attacker sends a small request to a third-party server with the victim's address spoofed as the source, and that server sends its (much larger) reply to the victim instead of back to the attacker. UDP's use cases article and the recursive DNS lookup article already walked through exactly this mechanism using DNS as the concrete example — a roughly 60-byte spoofed query producing a response thousands of bytes larger, with the entire multiplied reply landing on a victim who never sent the original query at all. The same reflection principle also works against NTP, memcached, and other UDP-based services that return more data than they receive, for the identical reason: UDP never confirms the source address before replying, so nothing stops the reply from going to the address in the spoofed packet's source field.

Protocol attacks exhaust a specific piece of server or network-device state rather than raw bandwidth. The TCP three-way handshake article already covered the canonical example — a SYN flood — in depth, including the SYN-cookie mitigation and the exact sysctl settings involved, so it isn't repeated here. The general pattern it illustrates is broader than TCP specifically: any protocol that allocates some resource on the first message of an exchange, before verifying the other side is genuine, can be exhausted the same way.

Application-layer (Layer 7) attacks are the hardest of the three to tell apart from real traffic, because every individual request is completely valid — a real HTTP GET, a real login form submission, a real search query — sent at a volume or pattern the application's own logic can't sustain, even though the network and transport layers underneath handle the traffic without difficulty. An HTTP flood is the most common form: thousands of ordinary-looking GET /search?q=... requests per second, each one cheap for the attacker to send but expensive for the server to answer if that endpoint triggers a database query or a slow computation. A volumetric or protocol attack usually shows up first as a spike in raw traffic or connection-state metrics; an application-layer attack often shows up first as the origin server's CPU or database load climbing while the actual bandwidth and connection counts look unremarkable, since the attack traffic fits entirely within normal-looking request rates from the network's point of view.

Reading the difference in practice

The three categories leave different fingerprints, and telling them apart is usually the first real diagnostic step during an incident, not an afterthought.

vnstat -l -i eth0
Monitoring eth0...    (press CTRL-C to stop)

   rx:    842.31 Mbit/s     40214 p/s          tx:     1.84 Mbit/s      1206 p/s

An interface graph like this one, showing inbound traffic far outstripping what the server's own uplink is provisioned for, points toward a volumetric attack — the pipe itself is the bottleneck, and no amount of application-level tuning fixes a link that's already saturated. Contrast that with ss -s during an application-layer flood:

ss -s
Total: 184
TCP:   163 (estab 158, closed 4, orphaned 0, timewait 3)

A connection count and bandwidth figure that both look completely normal, paired with a web server's own access log showing an unusual spike specifically in requests to one expensive endpoint, points toward an application-layer attack instead — the network layers see nothing unusual at all, because nothing about the traffic is unusual until you look at what the requests are actually asking the application to do.

Mitigation: absorb, filter, or push the fight upstream

Nothing on a single target server can out-scale a large enough volumetric attack — no amount of local tuning increases the capacity of an internet uplink that's already full. The realistic defenses work by moving the fight somewhere with more capacity, or by making the target cheaper to attack against in the first place.

  • Overprovisioned scrubbing services and CDNs sit in front of the origin server and absorb traffic at a scale the origin itself could never handle directly — this is the same role a CDN already plays for ordinary traffic distribution, applied specifically to absorbing an attack instead of just caching content.
  • Anycast spreads incoming traffic across many geographically distributed points by routing, rather than concentrating it all on one server's single network path — exactly the property the anycast article listed as a reason anycast is "widely used" for DDoS-resilient services: an attack aimed at one anycast address gets naturally divided across every announcing location a client's own network routes toward, rather than landing entirely on one machine.
  • Rate limiting at the application or gateway layer, covered in depth in this module's article on the subject, is the primary defense against application-layer floods specifically, since those requests are individually valid and can only be distinguished by frequency, not by content.
  • BCP 38 (source address filtering), an IETF best practice for network operators, closes off a prerequisite that reflection attacks depend on: it asks every network to filter outbound traffic and drop packets whose source address couldn't legitimately have originated from that network, which prevents an attacker on that network from spoofing someone else's address in the first place. It's a mitigation every network operator can apply to reduce the internet's overall capacity for reflection attacks, not something a single target under attack can invoke for itself.

Don't experiment with flood generation tools against any system you don't own and control

Even a small-scale test flood, run against a shared or production system without explicit authorization, is functionally indistinguishable from a real attack to the target and to any monitoring watching it — and in most jurisdictions, sending it without authorization is itself the criminal act a DoS/DDoS law describes, regardless of intent. Any hands-on testing belongs in an isolated lab environment against infrastructure you control, covered later in this course's hands-on module.

Practice exercises

  1. A server's bandwidth graph looks completely normal during an incident, but its CPU is pegged and its access log shows a huge spike in requests to /api/reports/generate, a known expensive endpoint. Using the three-category breakdown above, classify the attack and explain which of the three listed mitigations is actually appropriate here, and which two would do nothing for this specific case.
  2. Explain, in your own words, why a botnet-driven DDoS attack can't be stopped by blocking a single source IP address, the way a single-source DoS attack often can be.
  3. Using the DNS amplification mechanism already explained in the UDP use cases and recursive DNS lookup articles, explain what BCP 38 source-address filtering would have to prevent, upstream of the open resolver, to stop that specific attack from working at all.

A volumetric or protocol-level flood is loud by design — it announces itself the moment it starts, in traffic graphs and connection counts anyone is watching. A different category of attack works by staying completely quiet: instead of overwhelming a connection, it sits inside one, reading or altering traffic neither side ever notices is compromised. That's next.

Sources