August 27 TCRF DDoS Attack Postmortem – Xkeeper's blog

20 min read Original article ↗

…but first, a quick digression about what likely started it.

Our stance on AI agents isn’t much of a secret. I recently added a new feature to The Cutting Room Floor: If you visit the site with a “Claude-code” user agent… it adds you to a Claude user ban list. Then, if you try and visit the site later, without Claude — maybe because you wanted to investigate the “prompt injection” page it received — you’re greeted with a special error page telling you to get out, featuring a pixelated Claude logo:

"tcrf.net  403 - access denied", featuring two hands on either side of a low-resolution, upscaled Claude AI logo, with "Claude User Detected!" below it
Hello old friend

A Twitter bluecheck ran into this, evaded the ban, then proceeded to get increasingly mad at the fact he got banned. Not only did he dig up long-inactive versions of the “prompt injection”, but he then made up an entire story about how it zeroed a VM and wiped the OS, sent that made-up sob story to our host multiple times, and then got a Twitter mob going over it. Kotaku even covered some of this nonsense. Notably, when they asked both of us for comment, I responded, while the other guy… asked Grok for legal advice on suing for defamation.

LLMs rot your brain. Not even once.

I mention this backstory, because the ban and Twitter meltdown happened just before the attack started. The timing seems more than mere coincidence.

The DDoS attack itself

When discussing DDoSes affecting TCRF, they’re typically done via bots or scrapers. They request hundreds of pages, trying to exhaust the server’s CPU time generating responses nobody will read. Attacks like this can be worked against with mitigation tools like Anubis, which stop a bot from requesting pages until they spend a second doing math.

That wasn’t the case with this attack. The perpetrator here aimed to simply saturate the server’s network connection, overwhelming it with literal garbage traffic to a degree nothing legitimate could get through. It was bad enough, and extended enough, that Linode had to null-route (disable) our server’s connection — the DDoS traffic was starting to affect Linode’s other customers. Their infrastructure couldn’t handle the sheer amount of garbage traffic being sent to us.

network graph of our main linode, showing the various traffic levels over the last 30 days, including a huge spike and constant background radiation
You can also see the impact Cloudflare’s caching has on our bandwidth.

Unfortunately, anti-bot proxies like Anubis aren’t effective for this type of problem; you need a big enough pipe to handle all the traffic.

Below is a timeline of what happened, and what we did about it.

Pre-attack

※ (All times in this post are in Pacific Time unless otherwise specified.)

The first point I noticed something was up can be dated to this screenshot, taken August 27, 12:11 PM. The main indicator is the purple segment of the CPU; this is from the system dealing with a huge influx of garbage traffic. It’s not actually busy work (the green and red sections), it’s just trash.

htop's cpu meters, with the majority of them purple-colored
All of that purple? Bad.
a network chart showing two short-lived peaks, around 1600 Mbps and a higher peak of 2051 Mb/s
I have never seen this chart measured in Mbps before.

We were getting a massive flood of incoming traffic. The server wasn’t doing anything beyond dumping all of this in the garbage, but there was so much of that it was all it could do. This attack lasted for maybe half an hour, but was enough to make accessing the website nearly impossible during that time.

In retrospect, it’s possible that Linode’s automated DDoS mitigation kicked in temporarily, rather than the attacker themselves backing off.

Main attack starts (August 27)

another htop screenshot showing purple bars
I love purple, just not here

At 7:39 PM, another wave of the attack began, knocking things offline. The attack was sending a huge amount of trash to port 80, and even with most of it being filtered out before hitting any actual assets (either by ufw or nginx rules), traffic at that level was enough to overwhelm the server.

But before long, the traffic stopped. All web traffic. Even known-safe traffic, explicitly allowed through our server’s firewall, was getting dropped.

the network graph a few hours later, showing a smaller spike than then a last value of "85 kbps" (much lower than the average of ~44 mbps)
multiple emails alerting me that my linode, the one that runs TCRF, has exceeded the notification threshold for incoming traffic (10 Mbps) by averaging 74, 43, 375, and 14 Mbps (yes, three hundred seventy five)
Prior to this attack, I had gotten this notification 5 times. Ever. This attack gave me 46, and some of that was after I raised the threshold to 40Mb/s…

Initial investigation and response

We spent some time trying to troubleshoot. The Linode network graph showed no traffic; attempts to connect from various sources didn’t work, including ones I had specifically whitelisted in the on-server firewall. After exhausting all options, at 8:34 PM, we reached out to Linode customer support.

At 10:44 PM, we received a reply from Linode:

Hello,

Thank you for your patience while we investigated this.

We confirmed that an automated mitigation block targeting incoming TCP port 443 traffic was triggered at the router level in response to the recent DDoS activity against your IP (tcrf.net).

Because this block is managed by our automated DDoS defense system, we do not have a specific ETA for its manual removal. However, once the DDoS event subsides and attack traffic is clear, the system will automatically remove the block and restore normal HTTPS traffic.

We are actively monitoring the situation on our end to ensure connectivity is restored as soon as traffic conditions stabilize. Please let us know if you have any additional questions in the meantime.

In short: “There was so much traffic that we had to turn it off because it was interfering with our hardware. When the traffic subsides, it will turn back on automatically. There is nothing you can do.” Not ideal, but, well. There’s not much we could do: it was simply unreachable.

Day Two (August 28)

The DDoS attack had not stopped by this point, over 12 hours. We reached out to Linode and received this response, at 8:56 AM:

Hey there,

Thank you for following up, and I sincerely apologize for the delay and continued disruption to your service.

The automated router-level mitigation that W previously mentioned is still active as our network systems continue to handle the ongoing attack traffic against your IP. We are actively tracking the situation on our end and will reply here with an update as soon as we can.

In the meantime, please feel free to reach out if you have any further questions or if we can assist with anything else!

Best regards,
K

At this point, I began preparing a second server to host a “status page” while the attack was ongoing. Its only purpose was to serve a tiny HTML page (under 3 KB). We switched over the DNS entry, and presto! Status page.

a screenshot of our status page as it was early august 28, talking about visiting our bluesky account @tcrf.net and with links to our discord and patreon / kofi

Job done, I got up and decided to do something else productive, like have breakfast, take a shower, maybe even run an errand.

Overexcited host voice: You won’t believe what happened next!

a network graph of the second linode, with a big 1150mbps spike again
From our “backup” server.

Yep. Temporary site online? Better knock that one down too. And so they did; down goes the backup server.

If that wasn’t enough, our “friend” was also going after auxiliary services I run, including this very blog:

Uptime Kuma showing a flood of downtime notifications along the right side. the sites show as "up" because the history delay is pretty short (30 minutes) and they had recovered at this point
From a few hours after it happened, but you can see the huge pile of notifications it generated.

In this case, there’s nothing I can do. Most of these are simple shared hosting, not even a VPS, and in those cases I couldn’t even use something like Anubis if I wanted to; it’s entirely out of my hands. Thankfully, the attacks on the other websites mostly stopped after a little while.

While all of this was going on, I had also checked to see if Linode had anything that might help. They offer a “cloud firewall”, so I inquire about it (along with the general status of things). At 8:36 PM, I get a response, emphasis added:

2026-08-28

Hi there,

I completely understand wanting a path back online sooner rather than later. Unfortunately, Cloud Firewall wouldn’t help in this specific case, since the block is happening further upstream, before traffic even reaches your Linode’s own firewall rules. The most reliable path here is letting the automated mitigation run its course, it’s specifically designed to lift once the attack traffic settles, and that’s the resolution we’d recommend standing by for.

We’re actively monitoring the situation on our end and will let you know as soon as we see things stabilize.

Regards,
N

We’re keeping a close eye on this to get you back to normal as quickly as possible. Please don’t hesitate to reach out with any questions in the meantime, we’re here to help!

So, there’s still pretty much nothing I can do but wait, and now they’ve knocked down both the primary and the backup server.

Well, at least it can’t get any worse.

gmail inbox screenshot: "Request for Comment: Kotaku. - Hi X! Hope you're well. ..."
is that good

(gritting teeth) Well, at least it can’t get any worse. Ultimately, the other party failed to comment (again, asking Grok for legal advice instead), and you can read that whole story above.

On top of all of this… we were also getting spurious abuse reports sent to Linode / Akamai, with no details and made up URLs, forcing us to file similarly pointless “this URL does not exist, and has never existed” responses. (Linode’s response at one point included a note that they were obligated to open them, and thanked me for always promptly responding.)

Day Three (August 29)

Today starts off with what seems to be good news. Linode support messages me at 7:07 AM:

Hello,

I checked a few moments ago and I didn’t see any null routes for your IPv4 address in our system, so it looks like the attack has stopped and the service is back to regular operation.

Can you please let us know how things look on your end at this time?

All the best,
A

This is about one and a half days into the attack, now, and it sounds like things have finally let up. We start checking how things look on our end, and… nothing. The uptime tracker still reports it’s down; while my SSH connections are up, the traffic logs on both servers are still empty. At 7:50 AM, we reply with our findings, and at 9:09 AM Linode support responds:

Hello,

I took a look at both of your Linodes to see what is holding up the traffic. We can confirm the automated mitigation blocks were removed for both IP addresses.

The block on your original IP (xx.xx.xx.xx) was cleared yesterday at 4:43 AM EDT, and the block on your secondary IP (yy.yy.yy.yy) was removed today at 11:08 AM EDT.

I went ahead and reset the networking on our end to make sure everything is clear on the routing side.

[…]

They also provided some advice (they offer enterprise-level firewalls, and a third-party proxy solution is likely best). But, we should be good to go, right?

Support and I go back and forth, troubleshooting the networking — booting into Rescue Mode, doing additional network tests — but, after several different steps… 2026-08-29 3:08 PM:

Hello,

Thank you for confirming that for us. I wanted to confirm that our engineers are actively investigating this with us now. They have discovered that the IP xx.xx.xx.xx is currently being filtered as a result of our DDoS protection, and I can confirm that the current connectivity issue to that IP is a result of that block.

They are currently working to remove that block if they determine that traffic has returned to safe levels. We will keep you updated on this and will share any new information as it becomes available. We have noted the urgency of this situation to those involved, and so we are working to resolve this as soon as possible.

Thank you for your continued patience throughout this. Please don’t hesitate to contact us if you have any questions in the meantime.

Regards,
C

From 7 AM to 3 PM, I was sitting around my desktop, stuck between running various troubleshooting/diagnosis steps, and waiting for support replies… and, well, it was all for naught. The block was never lifted. The attack hadn’t ended. Support confirmed this at 3:49 PM after I asked them to clarify the discrepancy, emphasis added:

Hello,

I apologize for the confusion. The message you’ve quoted from my teammate V was based off of the information and monitoring that our Support team had available to us at that time, which indicated the block had cleared.

Because connectivity had not resumed after our Support team observed messages indicating a removal of the block, we then requested additional investigation from our internal teams. Further investigation with those teams has now confirmed that the block has remained in place for the duration, and has not actually been lifted.

They have also now confirmed that the DDoS attack traffic targeting your Linode IP has not returned to safe levels since its initial onset, which occurred about an hour prior (August 27 around 10:35pm ET) to you opening this ticket.

Since the volume of the traffic is still high at this time, the DDoS mitigation block remains in place and will be removed automatically once the traffic to the IP returns to acceptable levels.

At this point, the attack has been going on for 1 day, 20 hours: 8/27 7:35 PM to 8/29 3:49 PM.

I get up and take a break for a while, to consider next steps. It’s clear waiting isn’t going to work. Whoever is doing this has more money than sense. Since it’s pure trash traffic, something like Anubis won’t help. We need a layer-3 service that can handle it.

It’s not much of a secret that I’m not the biggest fan of Cloudflare. I settle on trying out one of their competitors: Fastly.

Life in the Fastly lane

Fastly has (had?) an “Under Attack” link in the header, which suggests signing up for an account and routing your traffic through “Fastly’s DDoS mitigation”. So I do, setting it up in front of our backup server. While Linode won’t let me assign a new IPv4 to the attacked machine outright, it will let me swap IPs… so I make a new Nanode™, swap the IPs around, and now the backup server has a fresh IP address. Nothing to it.

My initial impression of Fastly isn’t too bad. We get it online around Aug 30, 12:00 AM. I set a $10 monthly spend limit, get things configured, and before long, the backup server is back online! I’ve spruced it up a bit by this point to feature some simple icons and status updates as things progressed.

a screenshot of the backup page, featuring simple ms paint icons for discord, bluesky, patreon, and ko-fi
Including classic TCRF-brand MS Paint art!

Job done. Backup site online. I go to bed.

Day Four (August 30)

Linode reaches out this morning at 10:37 AM (2 days, 15 hours into the attack):

Hello,

The attack appears to be ongoing. If you would like to try and access your linode using another IP, you can try adding a second one to see if you can use it to connect, as P said before.

[…]

They are suggesting more or less what I’ve done with the backup server: a second IP address that we keep private. We’re going to do just that, and the backup server is the preparation for it. Making sure configurations and such set are up before unleashing it on the “real” server.

So far, so good! Everything’s coming up Milhouse.

Move to Fastly and things break

With almost comical timing, at 11:00 AM, I get an automated e-mail from Fastly:

Spend limit exceeded
Your spend limit for the month is set to $10.00. Your current month-to-date spend is $21.00. You can monitor usage in real-time using Observability.

To view products with the most usage visit the plan usage page on the Fastly Control Panel.

Uhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh. Keep in mind that the entire backup site is about 25 KB uncompressed. Let’s check out that Observability:

a chart of requests to our backup site through fastly, showing about 686,000 requests total over ~17 hours
Total: about 686k

Our simple downtime page has accumulated nearly 700k requests in 14 hours. (The full wiki typically serves about 5,000k/day.) Is that a lot for Fastly? I’m not sure. I’m confused as to how I spent $20 already. Let’s check out that plan usage page…

Plan usage: "August 2026: No usage"
"Billing Overview" - "Usage based" $0.00 + usage"

Excellent! I understand everything now.

At some point, some page reveals it is the “DDoS protection” I activated:

I've somehow spent $20.75 on DDoS Protection. When I checked the panel it suggested it had blocked exactly 0 (zero) requests

$20 on DDoS protection. I checked whatever page it was, and it said it had blocked exactly 0 requests and allowed 100% of them. I’m not really sure what it did, other than cost money. Since it had a literal 0% block rate, and it was something I activated on top of the basic account, I cancel it.

At some point around August 30, 2:30 PM, about 15 hours after we started using it… Fastly suspends our account.

"Thank you for your interest in Fastly's services. Your developer account has been deactivated due to a violation of Fastly's terms Terms of Service"

I have no emails, no notifications, no anything to indicate why. I am not sure what the “violation” is. We joke that it’s because I griped about their billing interface while Carnival Night Zone played. I send a support email at 2:46 PM.

We’ll skip ahead in the timeline momentarily to their response (Aug 31, 11:17 AM, almost a full day later), as Fastly exits the story afterwards:

Hello X, 

Thank you for your patience while I worked with internal teams on finding the cause here.

We were able to see the cause of the account being turned down was marked as Excessive Bandwidth Usage, and was disabled for bandwidth abuse. This appears to be because the account was a Dev account, and those are generally used for testing functionality or creating a POC, and not fielding that volume of bandwidth.

I’ll be honest: in the process of writing this (currently 9/23), I had to go check the archives to double-check that the instructions said, quote,

Under active attack? Create a free account to route your traffic through Fastly’s network in minutes for immediate DDoS mitigation.

What they don’t tell you is that the “immediate DDoS mitigation” is also measured in minutes (~900). At least for us.

The funniest thing about it happened a few days later, when this message hit my inbox:

fastly .. Your monthly security update:
DDoS requests: 3,909,513
DDoS events: 2
"ddos requests ... 84.69% of fastly customers have fewer DDoS requests than your account"
"DDoS events ... 42.50% of Fastly customers have fewer DDoS events than your account"
All of this in fifteen hours.

I had high hopes for Fastly, but pretty much every step (aside from initial setup!) was a blunder.

Meanwhile…

Back where we were, something else was happening to the backup server:

a CPU/Network chart showing a steady ~140% CPU (out of 200%) and ~60 Mbps in

In my haste to get Fastly set up, I had made a critical opsec error: Make sure the backend server only accepts requests from authorized frontends. (In practice, this just means “drop all traffic except for the specific proxy origins they give you”, it’s not that scary.)

I suspect that our attacker scanned Linode’s IP space and found the backup server by simply asking each one for our site, until he found the one that gave it. Oops. Oh well, lesson learned. We made sure to add the firewall rules first next time.

Enter Cloudflare

At Aug 30, 3:52 PM, tcrf.net was added to Cloudflare. At 6:17 PM, “Under Attack” mode was activated, and has remained on since. We decided to leave the backup server in place for a while until we could be sure everything was ironed out, set up some basic rules, etc… and it was a good thing we did: around 6:12 PM, we were hit by a DDoS through Cloudflare:

cloudflare dashboard showing 87 M requests, with a massive, 80M spike at 18:14

The perpetrator of this specific attack directly reached out to me via Telegram and Discord. I immediately blocked both. (I don’t have any solid evidence that any other attacks were related to this person.) Aside from that event, things were smooth: the backup site stayed online.

Day Five (August 31)

I send a message at 10:18 AM thanking Linode for the extra IP address, and mentioning that I’m curious if there’s any clue as to just how much traffic has been blasting our server.

Linode greets me with an update relatively early, at 10:52 AM:

Hi,

That’s very understandable, and I agree that this attack seems unusually sustained and targeted. […]

Due to security concerns, we generally aren’t able to share the specific amount or kind of traffic that will trigger our null routing, but I can confirm that this does seem to be quite a large scale attack. I also confirmed that the attack is still ongoing, as a block was just temporarily removed and then re-added a little bit ago.

Please let us know if you have any other questions for our team during this time, we thank you for your patience. We’ll provide any important updates here as we receive them

Regards,
B (he/him)

We’re now 3 days, 15 hours into this attack. I really, really wonder how much something of this scale costs.

I spent most of the rest of the day preparing the main server to be online again, cleaning out older firewall rules for newer and simpler ones, preparing the Linode Cloud Firewall for Cloudflare traffic, and otherwise getting ready for the relaunch.

Day Six (September 1)

(Discord screenshot) Hey folks! You shouuuuuuuld be able to access https://tcrf.net/The_Cutting_Room_Floor again as of right now. Thanks for your patience while we handled this...

In the coming days we'll probably have some cleanup to do and some kinks to iron out with the changes, but hey; we're back!

Midnight, September 1 — 4 days, 4 hours after the attack started — we’re back online. There’s a few tweaks to be made, security settings to be tweaked, and so on, but the site is back and browsable for everyone. The attack itself wouldn’t end for several days yet, but it was now fully mitigated.

The End (September 9)

September 9, 12 PM — 12 days, 16 hours after the attack began — it ends. Incoming garbage traffic finally disappears from both the main and backup servers.

backup server graph showing the attack abruptly ending, going from a constant 40Mbps in to 0
Backup server
primary server graph showing the same thing, but with constant normal traffic as well
Main server

At 4:22 PM, Linode support confirms that it’s over, and their automated mitigations have ended:

Hello,

I checked both of those IPs and it looks like the last networking block was removed around the same time that you also noticed the traffic dip, potentially indicating an end to these attacks! We’re going to keep this ticket open for a few more days just to make sure that things have actually subsided, feel free to reach out with anything else in the meantime.

Regards,
B (he/him)

Finally.

Ongoing Attacks

While the main DDoS attack ended, we still see sporadic HTTP-level attacks, lasting about 10 minutes each. They’re relatively infrequent, perhaps one or two per day, and not enough to majorly disrupt service. We can just tell people “yeah, wait a few minutes and it’ll work”; we’re still working to mitigate even those, but it’s a lot less critical now that the site is back to 99.5% uptime 🙂

a cloudflare dashboard screenshot showing 92.7M requests, with a mostly flat graph and a huuuuuuge peak around 7:30 AM
HTTP traffic for September 23. You can’t tell, but there’s actually normal traffic all around that spike, it’s just completely dwarfed in scale.

For similar reasons, we recently had to implement Cloudflare for our Rusted Logic domain. Publishing this post (and drawing attention to the attack, again) means that it’s very possible I’ll have to put this blog and the rest of xkeeper.net behind it, too. At least the process has been relatively painless.

To whoever is doing this: hi, please find a hobby that isn’t trying to take down my sites.

Positive Outcomes

In the process of mitigating, migrating, and updating things, we’ve made a lot of upgrades and improvements to the wiki and infrastructure:

  • Improved caching / distribution
  • Full IPv6 support
  • Automatic blocking of many bots and other nuisances, including Tor exit nodes
  • Unblocking most VPNs
  • Better embeds for Discord, Bluesky, etc.
  • Cloudflare’s automated Wayback Machine archiving
  • Better security, firewall, etc.
  • Support for HTTP/2 and HTTP/3
  • Basic analytics (more than simple nginx logs, at least)
  • Potentially more benefits?

My eventual goal is to have a non-Cloudflare proxy for logged-in users, so that people who can’t access it through Cloudflare can still view the site (e.g. ancient hardware, etc). But that’ll come once we finish getting the software more up to date and such; for now I’m just enjoying some (relative) peace and quiet.

Closing thoughts

I’d like to thank everyone for their patience and support while we weathered this attack. The support helped keep us going during the long nights spent trying workarounds and troubleshooting, and ultimately we came out of it stronger and better than before.

If you’d like to support us and the wiki, consider joining our Patreon or supporting us via Ko-fi. As always, thank you; it means a lot to us.

(Please keep any comments respectful.)