In short
- A denial-of-service attack takes a service offline by running out something it needs. A distributed one, a DDoS, does it from many machines at once, usually a botnet of hijacked devices, so there is no single sender to block.
- There are three families, named by what they exhaust: volumetric floods fill the network link, protocol or state attacks fill the tables that track connections, and application attacks keep busy the workers that answer requests.
- Each limit has its own meter: bits per second for links, packets per second for anything that handles packets one at a time, connections held for a table of state, and requests per second for the application.
- An attack only has to beat the smallest limit in the path, so a state or application attack can take a server down while its bandwidth graph looks almost normal.
- The family decides the defence: a full link can only be relieved upstream, a full table by not holding state for unproven clients and capping what each client may hold, and a busy application by telling real clients from fake ones.
On this page
- DoS and DDoS: one sender, or thousands
- Botnets: other people's devices, one command
- Three families, three things to run out
- Bits, packets, connections, requests: a meter for each limit
- One server, three attacks: a worked example
- Why anyone bothers
- Why the family decides the defence
- Mistakes people make about DDoS
- What to do before one arrives
- Questions
- Sources
In September 2016 a botnet of hacked cameras, home routers and video recorders pointed more than 620 Gbit/s of traffic at the website of the security journalist Brian Krebs, one of the largest attacks on record at the time.1On 25 September, with the site behind new protection, the same botnet came back with something that looked nothing like it: a flood of ordinary web requests, from a sample of more than 158,000 addresses.2
The first attack tried to fill the pipe to the server. The second aimed past the pipe, at the software that answers requests. That is the whole subject in miniature. A denial-of-service attack does not break in or steal anything. It wins by running something out, and there are three things worth running out: the capacity of the link, the tables a server keeps for its connections, and the workers that answer requests. Which one an attack goes after decides what it looks like on your graphs, what it is measured in, and what can stop it.
DoS and DDoS: one sender, or thousands
CISA defines a denial-of-service attack by its effect: legitimate users cannot reach a system, a device or a service because of something an attacker did.3 The UK's National Cyber Security Centre describes the attempt as overloading a website or network until it slows down or cannot be reached at all, and points out that the damage counts even when the attack is temporary and no data is touched.4
A plain DoS comes from a single source, one computer or a small number of them.5That can be enough: RFC 4732, the IETF's survey of denial-of-service problems, notes that a single well-connected machine can sometimes take a service down on its own.6 But one sender is also easier to deal with: unless it forges its source address, it stands out in every log, and blocking it far enough upstream ends the attack.
A distributed denial-of-service attack, a DDoS, uses many machines at once, usually a botnet of compromised computers acting on one command.5 Spreading the attack out changes three things. It multiplies the volume, since every machine adds its share. It hides the attacker behind the owners of those machines, which makes attribution harder.3 And it takes away the easy fix. MITRE's ATT&CK catalogue of attacker techniques notes that with enough machines taking part, each needs to send only a trickle, and at that point the attack is very hard to tell apart from real clients.7
Botnets: other people's devices, one command
A botnet is a crowd of hijacked internet-connected devices. The attacker gets in through security holes or weak settings, installs software that takes orders from a command and control server, and from then on can point the whole crowd at any target. The owners are victims too, and they rarely notice: CISA notes that owners often never learn their device is infected, and that one attacker could take over hundreds of thousands of them.3
Mirai, the botnet behind the Krebs attack, is the textbook case. It spread by scanning the internet for devices that still accepted one of 62 common factory usernames and passwords, and it mostly caught home routers, network cameras and digital video recorders.1 Its author claimed that more than 380,000 devices took part in the Krebs attack, and a separate Mirai attack on the French host OVH was at least 1.1 Tbit/s and perhaps as large as 1.5 Tbit/s.1 Researchers who followed the botnet for seven months counted a peak of about 600,000 infected devices.2
Divide CISA's two figures and the trick becomes clear: 620,000 Mbit/s shared across 380,000 devices is about 1.6 Mbit/s each. No single camera sends anything alarming, and no single home connection fills up. Only at the target does it add up. Mirai's source code went online at the end of September 2016, so others could build attacks from it too,1and botnets are rented out too, to "attack-for-hire" services that let people with no skill at all launch an attack.3
Three families, three things to run out
Security agencies sort attacks by method. CISA, the FBI and MS-ISAC use three types: volume-based, protocol-based and application-layer.5 The names are useful, but what matters to you, as the person whose server is going down, is what each one runs out. Traffic reaches an application through a chain of limits, and an attack only has to exhaust the smallest of them.
| Volumetric | Protocol or state | Application | |
|---|---|---|---|
| What it runs out | The capacity of the link | Tables of connection state: half-open connections, a firewall's connection table | Workers, CPU time, database capacity |
| Where that limit sits | Before your server | In the kernel, a firewall or a load balancer | In your application |
| Measured in | Bits per second | Packets per second; for tables, connections held | Requests per second |
| A typical example | Amplified replies from public UDP services | SYN flood | A flood of searches or logins; HTTP/2 Rapid Reset |
| On a bandwidth graph | Off the scale | May barely register | May barely register |
| Has to be stopped | Upstream, before the link | Before state is created, and by limits per source | Where requests can be read |
| In depth | Amplification attacks | SYN floods | How protection works |
Volumetric: fill the link
The first family is the bluntest. RFC 4732 calls it the simplest attack on a link: keep sending traffic that does not back off when the network is congested, and the link gets so crowded that real traffic loses too many packets to work.6 MITRE's example is 10 Gbit/s aimed at a server on a network with a 1 Gbit/s link to the internet.8 The router in front of that link can forward one gigabit a second and has to drop the rest, and it has no idea which packets were yours.
Attackers rarely produce that volume from their own machines. The usual route is amplification: small requests, sent with the victim's address forged as the source, to public services that answer with much bigger replies. The guide to amplification attacks covers how that works. GitHub's own report of an attack in February 2018 describes exactly this, with exposed memcached servers as the amplifiers and a peak of 1.35 Tbit/s.9
Protocol and state: fill a table
Every connection a server accepts costs a little memory: an entry in some table recording who is talking and how far the conversation has got. Those tables have limits. The classic attack on them is the TCP SYN flood, which RFC 4732 describes as essentially a memory-exhaustion attack. The attacker starts connections and never finishes them, and if new half-open entries arrive faster than old ones time out, the server has no room left for real clients.6The handshake, and the SYN cookies that defeat the attack, have their own guide: SYN floods and SYN cookies.
The same trick works on anything in the path that keeps state. A firewall that tracks connections can be made to hold so many that it runs out of memory, and RFC 4732 notes that most firewalls then "fail disconnected", cutting off everything behind them.6 The CISA and FBI guide places protocol attacks at the network and transport layers, layers 3 and 4.5 What makes them dangerous is economy. RFC 4987 explains the appeal: rather than exhausting the network by brute force, a SYN flood goes after resources on the end host, and it takes fewer packets to run those out.10
Application: keep the workers busy
The third family goes after the program at the end of the chain. RFC 4732 lists what an application can run out of: memory, CPU cycles, disk space, the processes or threads it may use, and the number of simultaneous connections it is configured to accept.6 The CISA and FBI guide describes it as going after flaws in the application itself, so that the application burns its processor time or stops working properly, rather than swamping the network.5 In practice that usually means requests that look valid but cost a lot to answer. The UK NCSC's example is search: among the ways a content delivery network can help, it lists limiting the rate of requests to particular URLs, so that a stream of search queries cannot swamp the database behind the site.11
In 2023 Google reported what it called the largest DDoS attack to date: a peak above 398 million requests per second, using a new HTTP/2 technique called Rapid Reset, against 46 million for the previous year's largest.12CISA confirmed that the flaw behind it, CVE-2023-44487, was exploited in the wild from August to October 2023, and told everyone running HTTP/2 to patch.13
Real botnets use all three. Of the 15,194 attack commands researchers watched Mirai's operators send, about 33% were volumetric, 40% TCP state exhaustion and 35% application-layer (the published shares add up to slightly more than 100).2 The CISA and FBI guide makes the same point from the defender's side: the families are not mutually exclusive, and attackers combine them.5
Bits, packets, connections, requests: a meter for each limit
Each limit counts something different, so each has its own meter, and an attack is quoted in the unit of the limit it goes after.
Bits per second measure links. Ports, transit and upstream capacity are all sold in bits, so volumetric floods are quoted in Gbit/s and Tbit/s. A 1 Gbit/s port moves 125 MB of data a second, whatever that data is, and not a byte more.
Packets per second measure everything that handles packets one at a time: routers, firewalls, the network card and the kernel of your server. Each of them makes a decision per packet, and most of that work, reading headers and looking up a route or a rule, is the same for a small packet as for a large one. RFC 2544, the benchmarking method for network equipment, reflects this: it expects a vendor quoting a single headline figure to use the minimum frame size, and requires that figure in frames per second.14 The same fact explains why one link can carry very different packet rates. On Ethernet each frame costs its own bits plus a 64-bit preamble and a 96-bit gap,14 so a minimum 64-byte frame takes 512 + 160 = 672 bits of the wire, and 1 Gbit/s carries 1,000,000,000 ÷ 672 ≈ 1,488,095 of them a second. At the largest standard frame, 1,518 bytes, the same link carries 81,274.
RFC 4732 calls the worst case livelock: past saturation, more load means less useful work, because the machine is taken up with interrupts for packets it will never get round to processing, and the application those packets were meant for gets less and less of it.6 A packet flood can get there at a bit rate that looks modest.
Connections held measure tables of state. Protocol attacks are usually quoted in packets per second, because every packet costs a decision somewhere, but a connection table does not fill with packets. It fills with entries, and the number it holds is how many new connections arrive each second multiplied by how long each one stays. So a table has meters of its own: the entries it holds against its maximum, and the rate of new connections. A table can be full while the packet rate looks ordinary, as the worked example below shows.
Requests per second measure the application. A request is a unit of work: a page to build, a search to run, a password to check. What it costs depends on your code, not on its size in bytes, which is why the same few kilobytes can be harmless on a static page and ruinous on a search.
The public records show how far apart the units can be. GitHub's 2018 flood peaked at 1.35 Tbit/s, carried in 126.9 million packets per second.9 Divide one by the other and the average packet was about 10,640 bits, some 1,330 bytes: big packets, an attack built to fill links. The same bit rate in minimum-size frames would be about two billion packets a second. Google's figure, above 398 million requests per second, is in a unit that never appears on a bandwidth graph at all.12
- GitHub, 2018: peak of a memcached amplification flood
- 1.35Tbit/s
- The same attack, counted in packets per second
- 126.9million pps
- Google, 2023: peak of an HTTP/2 Rapid Reset flood
- 398million rps
One server, three attacks: a worked example
Take one ordinary server. It has a 1 Gbit/s port and 2 GiB of memory, and it runs a website whose search page is served by 8 worker processes. Suppose one search takes 50 ms of work, so each worker can answer 20 searches a second and the site as a whole can answer 160. Now aim each family at it in turn.
The volumetric flood. Take MITRE's example of 10 Gbit/s.8 The port carries a tenth of it, so the router in front of the server drops about nine packets in ten, from attackers and visitors alike, and a real visitor's connection stalls under that loss. The server itself receives a full gigabit, and nothing it filters frees up the link. RFC 4732 makes the point: by the time a flood like this reaches the server it has already used up the link, so dropping it there achieves nothing.6
The state attack. The server's firewall tracks connections with Linux's connection tracker, conntrack. By default its table holds as many entries as it has hash buckets.15 The documentation gives the bucket count as total memory divided by 16,384,15 but in the kernel's code that is only the first step: any machine with more than 1 GiB of memory gets a flat 65,536 buckets, or 262,144 on a 64-bit machine with more than 4 GiB.17 So this server can track 65,536 connections.
Filling that table with junk is harder than it sounds. When the table is full and a new connection needs an entry, the kernel searches up to eight hash buckets, starting where the new entry would go, for one it has not marked as assured, and deletes it to make room. The code calls this early drop.17 A TCP entry is marked assured once its handshake completes.18 So one-way floods and half-open connections are thrown out as fast as they arrive, and an attack on this table has to look like real connections. A botnet can manage that, because its machines are real: they finish the handshake and keep the connection open, and an established TCP connection may sit in the table for five days by default.15
Suppose the attacker has 10,000 bots and each opens 7 connections: 70,000, more than the table can hold. Opening them costs two small packets each. Keeping them open depends on the software at the server end, which closes a connection that sits idle; suppose it gives up after a minute, so each connection needs one small packet a minute. That is 65,536 ÷ 60 ≈ 1,092 packets a second, and in minimum-size frames 1,092 × 672 ≈ 0.73 Mbit/s: less than a tenth of one per cent of the port. Once the table is full of assured entries, a new visitor's first packet finds nothing to evict, and the kernel drops it and logs "nf_conntrack: table full, dropping packet".17 That goes for every new connection the firewall tracks, your own SSH login included.
The application attack. The same 10,000 bots each ask for one search every ten seconds. That is 1,000 searches a second against a capacity of 160, so the queue grows by 840 requests every second, and a real visitor's search waits behind all of them until it times out. At about a kilobyte per request the whole attack is around 8 Mbit/s. Each bot, at one request every ten seconds, behaves like one person clicking through the site.
Two of the three attacks win at under 1% of the port. If the only graph you watch is traffic in Mbit/s, you will see the first and miss the other two. Watch every meter instead. On Linux the counters are already there: every network interface has a statistics directory in sysfs,16 and conntrack reports how full its table is. Replace eth0 with your interface's name (ip link lists them):
cat /sys/class/net/eth0/statistics/rx_bytes /sys/class/net/eth0/statistics/rx_packets4821337762161033214sleep 10; cat /sys/class/net/eth0/statistics/rx_bytes /sys/class/net/eth0/statistics/rx_packets4833837762161133214sysctl net.netfilter.nf_conntrack_count net.netfilter.nf_conntrack_maxnet.netfilter.nf_conntrack_count = 2231net.netfilter.nf_conntrack_max = 65536The two reads are ten seconds apart. In between, 125,000,000 bytes and 100,000 packets arrived: 12.5 MB/s, which is 100 Mbit/s, in 10,000 packets a second, an average of 1,250 bytes each. The packet counter also counts packets the host later threw away, even ones dropped in the network driver,16 so it shows what arrived, not what was served. The last command shows 2,231 entries in the connection table against a maximum of 65,536.15 A count pinned at the maximum, with the "table full" message in the kernel log (dmesg shows it), means that table is the limit you are hitting. If sysctl says those keys are unknown, connection tracking is not loaded and that table is not one of your limits. Requests per second come from your web server's access log. Write down what normal looks like for each of them before you need to know.
Why anyone bothers
Motives rarely show in the traffic, but they explain who gets attacked. MITRE's catalogue lists what attackers have been seen doing it for: political aims, hacktivism, extortion, and distraction.8 Rented botnets make all of these cheap, since attack-for-hire services let people with no skill launch an attack.3 So the targets are not only banks and governments. The researchers who tracked Mirai found its victims ranged from game servers, telecoms and anti-DDoS providers to political websites, and about one in eleven of the attacks that named a port went after 25565, the usual port of a Minecraft server.2 Games draw more than their share of attacks, for reasons the guide on why game servers get DDoS attacks explains.
Why the family decides the defence
Each family exhausts something different, so each has to be stopped in a different place, and a defence built for one does little against another.
A volumetric flood has to be stopped before it reaches the link it is filling. RFC 4732 says the filtering has to happen somewhere nearer the attacker.6 In practice that means capacity upstream of you. The UK NCSC's view is that a determined attacker can almost always outsend an organisation on its own, so the provider has to be part of the plan.11
A state attack is beaten first by not holding state for clients that have not proved themselves. RFC 4732 puts the aim as avoiding any state until a handshake has confirmed the client's address, and names SYN cookies as one way to do it.6 That stops floods of half-open connections. It does not stop the worked example, where the bots finish the handshake, and RFC 4732 warns about exactly this: bots weaken any test of whether a client can be reached where it says it is, because a bot has no need to hide its address.6 What helps there is a cap on how many connections one address may hold, which forces the attacker to find more bots. A bigger table on its own only raises the count: double it to 131,072 and the same bots need 14 connections each, about 1.5 Mbit/s to hold.
An application attack passes the link and the tables looking entirely legitimate, so it can only be stopped where requests can be read, by telling real clients from fake ones. RFC 4732 says that, short of vast spare capacity, the only real answer is to find something a genuine user can do that an attacker cannot.6 Per-URL rate limits help, as in the NCSC's search example,11 and so does patching: Rapid Reset abused a weakness in HTTP/2, and CISA's advice to anyone serving HTTP/2 was to apply patches as they became available.13
Real protection stacks these: capacity far upstream, filtering close to the server and checks in the application. The guide to how DDoS protection works takes each layer in turn, including what an upstream filter can and cannot see.
Mistakes people make about DDoS
Judging an attack by the bandwidth graph. A server that is down while its traffic graph looks quiet may still be under attack, as the worked example shows. Look at packets, connections and requests.
Expecting the server's firewall to save it. A firewall on the server only sees what fits through the link, so a full link is lost before the firewall is involved. And a firewall that tracks connections is itself a table that can be filled.6
Blocking addresses one at a time. A distributed attack is built so that each sender looks small. In the second Krebs attack, a single sample held 158,839 attacking addresses,2 and in an amplification flood the addresses belong to innocent servers anyway. Blocklists help against a handful of senders and little else.
Calling every spike an attack. RFC 4732 notes that in principle a subtle enough attack cannot be told apart from a flash crowd, and that failed links, flash crowds and misconfigured bots all exhaust resources without any malice.6 A launch, a mention on a busy site or a broken client can look the same as an attack. Your baseline is what tells them apart.
Assuming nobody would bother. Mirai's victims ran from telecoms and anti-DDoS providers to game servers and relatively obscure websites,2 and you do not have to be the target to go down: CISA notes that when your internet or cloud provider is attacked, you lose service too.3
What to do before one arrives
Most of the useful work happens before an attack, while there is time to think, and the three families tell you where to look.
- Know your three limits. Your port speed, the size of your connection table, and how many requests a second your application can really serve at its most expensive page. The smallest of the three is the size of attack that takes you down.
- Record a baseline. Analyse your traffic regularly so you know what normal looks like;5 RFC 4732 adds that the monitoring has to be in place before the event.6 Keep bits and packets per second, the connection count and requests per second, not just one of them.
- Know what sits upstream. Learn what protection against denial of service your provider gives your account11 and what it does with a flood bigger than your port, and tell it as soon as an attack starts.5 A volumetric flood can only be handled there.
- Make expensive work hard to reach. Cache what can be cached, rate-limit the pages that hit the database, and keep web servers and proxies patched, since application attacks go for the costliest request you serve.
- Keep your own devices out of the crowd. Change factory passwords on routers, cameras and recorders, and keep their firmware current. Botnets are built from devices like these that nobody looks after.
Questions
What is the difference between a DoS and a DDoS attack?
A DoS attack comes from one source, one computer or a handful. A DDoS attack comes from many at once, usually a botnet of hijacked devices. The distributed kind is bigger and much harder to block, because there is no single address to shut out and each sender on its own looks harmless.
Can a firewall stop a DDoS attack?
Only the part of it that reaches the firewall. A flood that fills the link to your server is dropped before the firewall sees it, and a firewall that tracks connections has its own table that an attack can fill. A firewall helps against small attacks and misbehaving clients; large floods have to be stopped upstream.
How big are DDoS attacks?
The largest publicly reported ones run to terabits per second and hundreds of millions of requests per second: GitHub reported 1.35 Tbit/s in 2018 and Google 398 million requests per second in 2023. But an attack only has to be bigger than the smallest limit in your path, which for a single server can be a few megabits per second of the wrong kind of traffic, or less.
How do I know if my server is under a DDoS attack?
Compare what you see with what is normal for you: bits and packets per second on the network interface, the number of tracked connections, and requests per second in your access log. A sudden jump in one of them with no matching jump in real users is the usual sign. Record the normal values before you need them.
Can my own devices end up in a botnet?
Yes. Mirai spread through home routers, cameras and video recorders that still used factory passwords. Change default passwords, keep firmware updated, and do not expose device logins to the internet. Mirai lived only in memory, so a reboot removed it, but the botnet kept scanning, so a device that came back with the same password could be infected again.
Sources
- Alert TA16-288A: Heightened DDoS Threat Posed by Mirai and Other BotnetsCISA
- Understanding the Mirai Botnet (USENIX Security 2017)Antonakakis et al., USENIX
- Understanding Denial-of-Service AttacksCISA
- Denial of Service (DoS) guidanceUK National Cyber Security Centre
- Understanding and Responding to Distributed Denial-of-Service Attacks (PDF)CISA, FBI and MS-ISAC
- RFC 4732: Internet Denial-of-Service ConsiderationsIETF
- Endpoint Denial of Service, Technique T1499MITRE ATT&CK
- Network Denial of Service, Technique T1498MITRE ATT&CK
- February 28th DDoS Incident ReportGitHub
- RFC 4987: TCP SYN Flooding Attacks and Common MitigationsIETF
- Denial of Service guidance: Upstream defencesUK National Cyber Security Centre
- Google mitigated the largest DDoS attack to date, peaking above 398 million rpsGoogle Cloud (its own report of the attack)
- HTTP/2 Rapid Reset Vulnerability, CVE-2023-44487CISA
- RFC 2544: Benchmarking Methodology for Network Interconnect DevicesIETF
- Netfilter Conntrack Sysfs variablesThe Linux kernel documentation
- Interface statisticsThe Linux kernel documentation
- net/netfilter/nf_conntrack_core.c: table sizing and early dropLinux kernel source
- net/netfilter/nf_conntrack_proto_tcp.c: TCP connection trackingLinux kernel source