Where a DDoS defense sits decides what it can save
We got floods just from developing game servers, so we built a lab to test the obvious idea: when you're attacked, only serve clients you already know. It works, and then it doesn't, and the reason why is the whole point.
Run a game server for any length of time and you will eventually get hit. It does not take a grudge or a target on your back; pointing a Source or Minecraft server at the public internet is enough, because the moment it announces itself to the server browser its address is harvested and the junk traffic follows. We ran into this the boring way, just developing game servers, and it sent us down a rabbit hole worth writing up.
The obvious idea, and a good one: when you are under attack, stop trusting strangers. Only keep serving the clients that were already playing, and drop everyone new until the storm passes. So we built it and measured it, because "seems like it should work" is not the same as "works."
The lab
We built an isolated lab inside a throwaway container: a tiny game server, one honest player sending a steady stream, and an attacker firing a UDP flood with a fresh random spoofed source address on every packet. In front of the server sat a firewall with an allowlist. The rule that fills the allowlist is the interesting part: a source earns a spot only after it sustains a real session, several packets spread across at least a second of wall-clock time. A real player clears that bar in the first second. A flood of one-off sources, each appearing for a few milliseconds and never again, never does. A watchdog watched the packet rate and flipped the firewall to allowlist-only the instant it saw a spike.
It worked exactly as designed. The flood hit about 191,000 packets per second. The watchdog flipped to allowlist-only in under a second. From that moment, essentially none of the flood reached the game: the firewall dropped every unknown source, and the one real player was on the list.
And then the player dropped anyway
Here is the part that made the whole exercise worth it. Even with the allowlist doing its job perfectly, the honest player still lost about five seconds of play. The firewall was dropping the flood, the application never saw it, and the player was still knocked offline.
The reason is that dropping a packet is not free. Those 191,000 packets a second still arrived at the machine. The kernel still had to receive each one, run it through the firewall, and decide to discard it. That work, hundreds of thousands of times a second, pegged the CPU and starved the actual game process. The allowlist protected the application from the traffic. It did nothing to protect the machine from the cost of the traffic.
Three bars, not one
The mistake baked into "just block the bad traffic" is treating a flood as one problem. It is really pressure on three separate resources, in order:
Your uplink. The wire from your ISP. Once packets are on it, that bandwidth is already spent. Nothing you run at home can un-spend it, because the congestion is upstream of your front door.
Your host CPU. Every packet costs a cycle to inspect, even the ones you drop. This is the bill the lab ran into.
Your application. The game or the web app. This is the only one an allowlist or a WAF actually shields, by refusing junk before your code sees it.
An in-host defense sits at the last bar. It is genuinely useful, and when an attack is not about raw volume, a slow connection-holding attack, a login being hammered, a clever request pattern, it can be the whole answer. But the moment the attack is about volume, the fight has to move to the first bar, and the first bar is not in your house.
Play with it
Reading about three bars moving independently is one thing. Watching it is better, so we built an interactive sandbox. Pick an attack from across the network stack, launch it, and toggle defenses on and off while three meters, your uplink, your CPU, and your app, respond in real time. Turn on the allowlist against a volumetric flood and watch the app go quiet while the uplink stays pinned red. Then add an upstream defense and watch the flood get eaten out at the edge, before it ever reaches your pipe.
Open the DDoS sandbox (nothing to install, it runs in your browser).
What actually holds
Ranked honestly, for a small operator:
Do not be reachable. Most servers that get flooded never needed to be public. A private tailnet puts development and staging on addresses the internet cannot see, so there is nothing to flood. Free, and it closes the most common way small teams get knocked over.
Filter upstream. For anything that must be public, the only thing that beats volume is a defense that sits in front of your pipe: anycast scrubbing, or a filtered edge that fronts your origin over a tunnel so your real address never appears in the server browser. The flood dies on someone else's much larger network.
Then add the in-host layer. The allowlist, the WAF, the rate limit. Behind an upstream front, on the right attack, it is the difference between a clean server and a struggling one.
The allowlist idea was not wrong. It was just aimed at the wrong bar for the attack we were worried about. Knowing which bar you are defending is most of the job. This is the thinking that goes into the protected hosting we build, and it started, like most of our best work does, with getting annoyed by a real problem and refusing to hand-wave the answer.
Working on something similar?
We help turn rough technical problems into practical first versions. Send a short message and we can figure out the next step.
Book a call →