Join Nostr
2026-09-29 16:58:36 UTC

someone on Nostr: The day nos.lol got flooded by 580+ bots TL;DR: For a few days, a coordinated flood ...

The day nos.lol got flooded by 580+ bots


TL;DR: For a few days, a coordinated flood attack took nos.lol down, over and over. Firewalls and filters bought time but didn't stop it. What finally stopped it was a small change to the relay's own code: making it refuse read-request floods at the door. The relay has now run more than 20 hours without a restart, absorbing over 12 million junk requests — while under continuous attack.




It started quietly. The relay stopped answering. A restart fixed it. Then it broke again — and again, each time faster.

Two attacks were running at once:

A connection flood. Hundreds of machines opened as many connections as the server allowed, then held them. When addresses got blocked, fresh ones appeared. At its peak, bots occupied thousands of connection slots — around 26,000 simultaneous connections, with dozens of addresses sitting exactly at the server's per-address limit.

A spam wave. Bots pushed a torrent of machine chatter — encrypted blobs, discovery beacons, peer-to-peer signaling payloads. None of it was people talking. It was software treating the relay as free infrastructure: free storage, free broadcast, free message bus. Some of it was arguably "applications" — peer-to-peer tools that bolted themselves onto Nostr instead of running their own servers. The relay paid the bill for all of them.


Like most Nostr relays, nos.lol checks every incoming message through a spam filter before storing it. The filter is clever but single-file: one process, handling messages one at a time, like a single receptionist at the door.

Under normal load, nobody waits. Under a flood, the receptionist falls behind, and soon every worker in the building is standing in that one line. When that happens the relay stops accepting new connections completely. From the outside: timeouts, errors, a dead relay.

The collapse then fed on itself in a cruel way. Every restart dropped thousands of users at once, and they all rushed back in together — a thundering herd with the attackers hiding inside it. The relay drowned in its own recovery. Time-between-deaths went from 20 minutes to 16, to 6, then to 1. Nine restarts in about two hours.


The obvious response is banning. So we banned: the addresses holding too many connections, the addresses sending too many messages, the addresses that kept coming back. Around 580 bots were identified and firewalled across the day.

New ones kept appearing. Some rotated through home computers. Some rode through anonymity networks and shared VPN exits, where one blocked address takes innocent users down with it. Banning was necessary — and it was whack-a-mole. You cannot firewall a flood that owns more addresses than you can list.

Even the logs looked haunted for a while: addresses printed as garbled symbols, and log lines bleeding into each other. That one turned out to be our own bug — the relay stores addresses in a packed binary form, and a new log line printed them raw. The terminal did its best with bytes that were never meant to be text. Fixed with a one-line change; the flood data underneath was perfectly sane.

The answer was to teach the relay itself to say no. A small change to the relay's source code — about fifty lines — added request rate limiting: per address, and globally. Requests over the limit are refused before they touch the relay's internals, so the jam has nothing to feed on. The limits were tuned live, in production, in minutes. No restarts needed to adjust them.

The effect was immediate. The relay went from dying in 60 seconds to absorbing a 35-minute monster flood without a flinch — 800 to 1,500 junk requests per second rejected at the door, latency to real users barely moving.

The result:
Over 12 million junk read requests rejected so far — with nearly 300,000 burst-overflow requests politely turned away at peak.
20 hours 50 minutes without a restart at the time of writing. The previous record during the attack was 21 minutes.
Response times under fire: 25–135 milliseconds.
404 flood bots automatically identified by the request tripwire alone, on top of the hand-banned list.
Users stopped noticing anything at all.


If you operate strfry:
The fix that ended this outage was request rate limiting inside the relay itself. Everything else only bought time. PR is online, you can upgrade your relay to the latest version after PR is merged and new version tagged.