Coming Soon to BitNinja. Already in Production in CFM.

A one-person, Apache-2.0 WAF shipped most of BitNinja’s July newsletter back in February — and then kept going, two layers past where the newsletter stops.

This morning a BitNinja newsletter landed in my inbox with the subject line every product marketer loves: “New improvements are available.” Security and performance updates. Big friendly headings. A little rocket-ship energy.

I read it. Then I opened my own git history. Then I laughed, poured a coffee, and decided to write this.

BitNinja "New improvements are available" July newsletter

Up front, to be fair: BitNinja is a perfectly good product, these features are genuinely useful, and I’m not here to tell anyone they’re wrong. I’m here because the newsletter reads, almost line for line, like the changelog of a project I’ve been running on my own hosting network since February — a single Go daemon, Apache-2.0 licensed, called CFM (Configurable Firewall Manager).

Some context on pace before we go feature by feature. CFM’s version number is the release date — every .deb and .rpm is stamped YYYY.MM.DD because it was built and pushed out that day. The changelog file only starts on 17 June 2026, with a one-line footnote explaining why: the first ~1,000 pull requests, from March through June 2026, aren’t even back-filled into it — go read the git history for those. So keep “roughly a thousand PRs last spring, one human” in mind as we walk through what BitNinja is announcing as new.

1. “A smarter alternative to traditional CAPTCHAs”

BitNinja is announcing a JavaScript Proof-of-Work CAPTCHA — lightweight browser-side verification instead of squinting at fire hydrants, less third-party dependency, lower resource usage.

Great idea. CFM’s Challenge Engine has been doing exactly this since February: a JavaScript proof-of-work challenge, signed with HMAC, issued and validated by cookie, before a request is ever forwarded to the origin. No image puzzles, no third-party CAPTCHA service, no external dependency quietly leaking your visitors to someone else. It runs in two placements — nftables DNAT, or fully in-path through the edge proxy — and it fires in four ways: automatically when a vhost’s suspicion score trips, on specific paths, per-IP on unique-path/unique-host fan-out, and manually. There’s even challenge-abuse protection, so bots can’t turn the challenge endpoint itself into a DoS vector.

I’m not claiming I invented proof-of-work challenges. I’m claiming I shipped mine — and blogged about it — nearly five months before this email.

CFM JavaScript proof-of-work challenge page as a visitor sees it

2. “WAF Pro is now protecting your servers”

The newsletter says WAF Pro replaces WAF 2.0, SSL Termination, and Trusted Proxy with a single unified engine — stronger protection, lower load, simpler architecture.

Unifying your WAF layers is the right call. CFM’s WAF is a fast in-path Lua pipeline: 66 detectors across nine rule-ID groups (1xx–9xx), with severity aggregation (every rule runs, the strongest action wins, order doesn’t matter) and — here’s the part that matters — four per-rule modes: disabled, logonly, challenge, block.

That’s not one “WAF Pro” on/off switch. That’s every single rule independently dialable, because a rule you can’t run in log-only first is a rule you can’t safely turn on against real customer traffic. The standard rollout is literally written down: land a new detector at logonly, watch a full week of production traffic, promote to challenge, watch another week, then promote to block. Never logonly → block directly.

And the detector inventory covers things most rule sets don’t bother with: Log4Shell plus its evasion variants, Java deserialization, PHP wrappers, polyglot uploads, PHP-webshell-in-a-zip, C2 paste-site tunnels, coinminer pool URLs, bad UTF-8 encoding, Windows LOLbins. Every one of them FP-tested against actual production traffic, not copied off a generic CRS list.

Sometimes the advantage of being one person is that you never built the three separate products you now have to merge into a “Pro.”

CFM-WEB WAF report showing per-rule modes: disabled, logonly, challenge, block

3. “New SOS Mode for attack situations” — Coming Soon

And here’s my favorite. Marked, in the email, COMING SOON.

The pitch: during a DDoS, you’ll soon be able to flip on SOS Mode from the console, which prioritises protection for the duration of the attack and then turns itself off automatically once it’s over.

Reader. CFM has a manual force-challenge that puts an entire vhost under the challenge wall on demand. It is one command:

cfm webtop challenge on <vhost>

Shipped. Not coming soon. And it doesn’t stop at a manual switch — the same engine escalates automatically, off live-traffic heuristics that read exactly like a DDoS fingerprint:

TriggerWhat it watches
IP_RPSraw request rate per IP
IP_404404 floods — scanners / path-probing
IP_403403 rate — auth / WAF block bursts
MALPATHhits on known-malicious paths
AGENTbad-user-agent hits
40X_COMBO403+404 combos — the probing pattern

So the panic button exists and the system is usually smart enough to hit it for you. We even picked the same name — mine’s called the “SOS” challenge. I’d apologise for the collision, except mine was in the commit history first.

CFM-WEB management interface

And then, two layers past where the newsletter stops

Here’s the thing the CAPTCHA / WAF / SOS newsletter doesn’t mention at all: everything above happens at the HTTP edge. That’s one layer. CFM is a five-layer stack, and the bottom two live in the kernel, where the newsletter’s roadmap doesn’t go:

  • kernsec — a preemptive, KSPP-grade kernel-surface hardener (production-mature). It applies hardening sysctls, boot-arg policies, risky-module blacklists, and mount-option audits, tier-by-tier, fully reversible with a rollback command and a safety preview before it touches anything. It shapes the host before an attack lands, so a foothold has less to pivot through.
  • cfm-lsm — a BPF-LSM behavioural layer (CO-RE BPF, no kernel module, no DKMS), shipping in monitor mode. It watches userspace behaviour at the syscall boundary and catches the things no log line ever shows: a PHP-FPM worker exec’ing a payload straight out of memfd_create (the canonical fileless-malware trick), or a process with its stdio wired onto a remote TCP socket (the reverse-shell fingerprint). The BPF programs pin to bpffs, so kernel-side detection survives a daemon restart.

I’m being precise on maturity on purpose — kernsec is production-mature, cfm-lsm is an MVP running in monitor mode. But the point stands: BitNinja’s announcement is catching up to my top layer. There are two more underneath it that a WAF, by definition, cannot see.

“But a solo project can’t do the network-effect part”

The usual rebuttal writes itself: sure, a hobby project can bolt on a CAPTCHA, but the real value of a commercial vendor is the network effect — shared threat intelligence across thousands of protected servers. You can’t get that from one person.

Except the management side of CFM already does the network part:

  • Shared IP intelligence — blocklists distributed across the protected fleet, so an attacker burned on one node is known to the rest.
  • Global unblock engine — because shared blocklists without a fast, central way to un-block a false positive is just an elaborate way to take down your own customers.
  • RBLDNSD — serving that reputation data out as DNS blocklists.
  • Phishlist — tracking and distributing known phishing domains.
  • Custom ClamAV signatures — shipping our own malware domain and hash signatures on top of stock ClamAV, so the scanner knows the threats actually hitting the network.
  • Statistics — the boring, essential part: what’s being challenged, blocked, and why.

That’s the “shared intelligence platform” bullet point, running in production.

So what’s the actual point?

It isn’t “BitNinja bad.” Their engineers are solving the same problems I am, the features are good, and being a well-resourced company with a roadmap, a support desk, and a marketing department is a completely legitimate way to exist. It’s a real product serving real customers at a scale I’m not pretending to match. My contributor list, for the record, is: me.

The point is smaller, and I think more fun. When one person has a real network to defend and no committee to ask, the distance between “we should build that” and “it’s live” collapses. No quarterly planning cycle. No “coming soon.” And “in production” isn’t a figure of speech here: these rules get tuned against real logs — a recent WAF false-positive pass went through roughly 256,000 WAF records across a six-server fleet before a single rule got promoted to block. You have the problem on a Monday and the fix in production by the weekend, because the person who wants it and the person who ships it are the same tired human.

So — genuinely — thanks for the newsletter. It’s a lovely validation email. It just turns out your roadmap is my git history, and my git history is about a thousand PRs ahead.

The coffee’s cold now. Back to the logs.


Related reading on CFM