Swatter Swarm — Share Confirmed Attackers Across Your Fleet, on a Hub You Own
By Josh Comstock · July 2026 · ~7 min read
Here's a thing that always bothered me about running more than one server. One box catches a scanner the hard way — it takes the hits, scores the IP, earns it a permanent ban across a few days of bad behavior. And the box right next to it? It knows none of that. When the same scanner comes knocking an hour later, server two starts from zero and relearns the whole lesson, one probe at a time.
Multiply that by a fleet. Every server paying full price for a lesson the fleet already learned. That's just wasteful.
Until now, Swatter had no reputation network of its own — it corroborated against free feeds like IPsum, Spamhaus, and AbuseIPDB, but it didn't carry its own shared intelligence the way CrowdSec does. That was a deliberate gap, not an oversight. A global community blocklist means trusting strangers' data and shipping your own offenders off to somebody else's network. That trade never sat right for a tool whose whole pitch is no phone-home.
Swarm is the version that does sit right. It gives Swatter the network effect — one box learns, the whole fleet blocks — without a single stranger in the loop and without your data leaving your infrastructure. It's a fleet reputation network you own outright.
What Swarm Actually Is
A hub is a small Cloudflare Worker plus a D1 database that you stand up — about five minutes with Wrangler. One hub per operator. Your boxes only ever talk to your hub. There is no Peace Harbor server in the middle, no shared pool, no global feed. If you run eight servers, you've built a private eight-node intelligence network and nobody else can see into it or contribute to it.
The loop is simple. After each scan, every box publishes the attackers it has confirmed. The hub merges them and hands back one decaying blocklist. Every box consumes that merged list on the next pass. That's the whole shape of it — publish, merge, consume — riding on the cron Swatter already runs, no daemon, no new moving parts on the box.
What Gets Shared — and What Doesn't
Only confirmed, enforced permanent bans leave a box. Not what it's watching. Not temporary blocks. Not anything it merely scored and let ride, and nothing from a dry run. A permanent ban in Swatter is already the high bar — an IP that misbehaved, got a temporary block, came back, and earned its way up the ladder across days. Those are the addresses worth telling the fleet about, and they're the only ones Swarm sends.
And before a single address goes out, it runs four gates:
- the strict IP/CIDR validator, so nothing malformed ever ships;
- the unsafe-target guard, so a
0.0.0.0/0-shaped mistake can't propagate; - your never-block set — Cloudflare's ranges, your allowlist, your monitoring;
- and a fleet canary (
SWARM_ALLOW_FILE): CIDRs you name that are never published and never acted on, no matter what.
Publishing is fail-soft. If the hub is unreachable, the box shrugs and retries next cycle — it never delays or aborts a scan to talk to the network. Protecting the box always wins over feeding the fleet.
What Comes Back — and Here's Where I Stay Honest
To consume the merged feed, you add swarm to INTEL_PROVIDERS, right alongside the free feeds. From there it behaves like any other reputation signal, with one detail that matters: the score scales with corroboration. One host saw this IP? That's SWARM_BASE_SCORE — 70 by default. Each additional box in your fleet that independently confirmed the same address adds 15, up to a cap of 100. An attacker three of your servers already banned shows up on the fourth carrying a 100. The fleet's agreement is the confidence.
Now the honest part, because I'd rather tell you the limit than have you discover it. In the default mode — SWARM_ACTION="boost" — the swarm signal can only raise a score, never act on its own. It makes a receiving box quicker to swat an IP that's also already misbehaving on it. That's escalation assist. It is genuinely useful, and it is not pre-emptive blocking. I'm not going to dress it up as more than it is.
If you want true pre-block — act on box B before the attacker has done anything to box B — that's the opt-in SWARM_ACTION="corroborated-block". It proactively temp-blocks a feed IP once at least SWARM_MIN_CORROBORATION distinct enrolled hosts have confirmed it (two, by default). And it earns its aggression honestly: every proactive block routes through the exact same choke every other Swatter block goes through, so your never-block rails, the validator, the unsafe-target guard, and the direct-vs-proxied plane classification all still apply. Swarm can make Swatter act sooner. It can't make it act recklessly.
Why It's Yours, Not Everyone's
This is the part I care about most, so let me walk it plainly.
There are no open contributions. Every box that feeds your hub is a box you own and enrolled yourself. That single decision erases the whole category of malicious contributors — there's no stranger poisoning the well, because there are no strangers.
Every box carries its own key. Enrollment doesn't just register a host — the hub issues that box its own write token, bound to its identity, and from then on the token is the identity. The hub ignores whatever host ID a request claims and derives it from the credential instead. So a leaked token buys an attacker exactly one thing: the ability to publish as that one box — which you revoke with a single swatter swarm enroll --rotate. It can't speak for a second host. It can't manufacture agreement, because corroboration is counted across distinct enrolled hosts, each holding a key only it has. Corroboration you didn't authorize is corroboration that doesn't exist.
One box's mistake can't take down the fleet. The fleet canary is there precisely for the nightmare — a box confidently publishing an address that turns out to be your monitoring service, or a customer's whole range. Name those CIDRs in SWARM_ALLOW_FILE and they are structurally un-publishable and un-actionable across every node. And if a bad address does slip out, swatter swarm purge --yes pulls everything that box ever contributed back out of the hub in one shot.
The list forgets. The hub prunes on a TTL — a week by default — so the blocklist decays. An IP that reformed, or a recycled address handed to someone new, ages out on its own instead of haunting your fleet forever. And a stale feed doesn't quietly rot: past SWARM_MAX_AGE_DAYS the signal is ignored and Swatter warns you, rather than acting on week-old intelligence as if it were fresh.
Put it together and the difference from a global network isn't cosmetic. Your confirmed offenders never touch a third party. Your fleet's intelligence stays your fleet's. You get the network effect and you keep the sovereignty. That's the whole point.
Turning It On
Stand up the hub from the hub/ directory — wrangler d1 create, apply the migration, set three secrets, wrangler deploy. The printed URL is your SWARM_HUB_URL. Then, on each box, point Swatter at it and enroll once:
# in swatter.conf
SWARM_ENABLE="true"
SWARM_HUB_URL="https://swarm.your-domain.com"
INTEL_PROVIDERS="ipsum spamhaus abuseipdb greynoise swarm"
# once per box, operator-run (needs the enroll token)
swatter swarm enroll
Publishing starts on the next scan. Consuming starts as soon as swarm is in your providers. Want to see where a box stands? swatter swarm status prints the hub, the action mode, the corroboration threshold, and a live health check. Want out? swatter swarm disable. Everything is inert until you deliberately switch it on — SWARM_ENABLE ships false, and a box that never enrolls never says a word to the network.
That's Swarm. One box catches the attacker, and the whole fleet blocks it — on a hub you own, with every guardrail still standing, and not one byte handed to anyone else.
Related: CrowdSec vs Swatter vs fail2ban for cPanel servers behind Cloudflare · How Swatter decides who to block.