status update:
2450+ bots banned. attacks are continuing. now thinking about doing an IP reputation database (and possibly import a database available online). turns out there are millions of compromised devices...
nos.lol is now also new paradigm (go+python) write policy. expect faster writes. stable reads. except when the attacker chooses to send REQs at the same time (the bots go silent for a while and then all request to read at the same time)
nostr.mom's nsfw checks using LLM and spam checks using LLM returned. reports are sent to nostr.mom as kind=1984.
started collecting long term data for calibration.
LLMs / vibe coding handled the past days very well. now i need to code something that constantly watches what is going on (possibly using an LLM on openrouter), weekly recalibrates constants based on data, ... fully agentic op..
spent probably ~50 USD on GLM 5.3 mostly and some 5.3 flash.
someone
npub1nlk8...jm9c
๐คฑ nostr.mom had ~5 minutes of downtime this afternoon: its write policy got replaced.
Old: a Python script that had grown for years and single-handedly judged every event. New: warden โ a Go plugin, with spam scoring decoupled into a separate LLM service. Verdicts stay fast under load, detection is smarter (batch LLM scoring, similarity matching, sender reputation), and all existing events made it through the switch.
nos.lol gets the same upgrade once this one soaks. If something of yours got wrongly rejected, let me know โ it's still calibrating.
open sourcing my web of trust script's vibed version.
web of trust scores are checked in many places in my scripts. both relay moderations and building datasets for llm training.
some friends asked whether i can open source some scripts. so decided to start with this. this algorithm has served me well for 3+ years. currently still using old manual coded version but i may switch to this if it performs better (most probably).
GitHub
GitHub - etemiz/wot
Contribute to etemiz/wot development by creating an account on GitHub.
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.
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.nos.lol db size 587 gb
pruning older, less important, low WoT ones