WAF - CyberMind-FR/secubox-deb GitHub Wiki

sbxwaf — the standalone WAF 🛡️

EN | FR | 🟡 WALL | sovereign application firewall

Pattern matched, ban applied in the kernel. No third-party service sits in the decision path.

What it is for

sbxwaf is the Go web application firewall of SecuBox (package secubox-waf-ng, unit secubox-waf-ng, listening on 127.0.0.1:8085). All public traffic goes HAProxy (TLS 1.3) → sbxwaf → nginx. It inspects requests, blocks and bans, lures scanners, and feeds the intelligence layer (Actor-Intelligence). Its admin views are also assembled in the SOC.

WAF overview

How it bans

request → sbxwaf → pattern → nft set (waf_ban / waf_ban6)
                              ↑
                       chain waf_drop, hook input, priority -100
                       ip saddr @waf_ban counter drop

The chain is the part that matters. A populated nft set that no rule references blocks nothing. sbxwaf therefore creates the chain and both rules at startup, preceded by a flush chain (add rule is not idempotent). Each element of the set carries a packet counter, which the end-of-ban re-evaluation reads (see below).

The admin view

Open /waf/ (for instance https://waf.<box>/, LAN only). The default tab is the Overview; six more tabs are standalone pages in the common Aurora style (tiles, inline SVG charts, lists, no external library). They are read-only: banning and unbanning stay in the API (and are written to the audit log).

Tab What it shows
Overview Tiles, world map, daily trend, categories, traffic by type, most targeted sites, last events, persistent actors, campaign fingerprints, what protects (measured state of each detection)
Threats Aggregated alerts and bans, by severity and category
Tracked attackers Attackers followed over time
Visits Traffic of visitors who are not attackers
Surfaces What is probed: surfaces, targeted accounts, decoys hit, countries of origin, names not served
History Daily trends and persistent attackers from the rotated logs
Campaigns Campaigns correlated from the threat log

Every page accepts ?embed=1 (framed, one column) and ?demo=1 (announced demonstration data). A measure that is missing is shown as "—", never as zero.

Threats Attackers
Threats Attackers

Modes, automatic bans and the response ladder

The common vocabulary (GET /api/v1/waf/enforcement/mode):

Mode sbxwaf flag Effect
PASSIVE_ONLY (observe) off observation only, no ban state published
SIMULATION propose candidates are written (decision WOULD_BLOCK), nothing is applied
ACTIVE (mitigate / block) auto bans are applied (decision BLOCKED)

Automatic bans, each with an hourly circuit breaker and graduated durations:

Flag Bans
--actor-ban tracked actors
--campagne-ban campaigns probing high-value targets (4 h / 24 h / 7 d)
--leurre-ban first contact with a decoy (1 h / 24 h / 7 d)
--mesures the response ladder published by sbx-actord: delay, proof-of-work challenge, tarpit, ban
--reevaluation logical kill switch: shortly before a ban expires, RELEASE or EXTEND; never permanent (30-day ceiling)

Never banned: private or local addresses, ranges listed in --actor-ban-protegees, verified search engines. Details of the ladder and the activation procedure (PASSIVE_ONLY → SIMULATION → ACTIVE): Actor-Intelligence. A change is applied with systemctl restart secubox-waf-ng (never SIGHUP).

Search engines are never banned

A robot is recognised by the proof the search engines document themselves: reverse DNS confirmed by forward DNS, in a closed list of domains (googlebot.com, google.com, search.msn.com, applebot.apple.com, crawl.baidu.com, yandex.*), strict sub-domain match. Result cached 24 h (1 h if negative). A spoofer (reverse written by him, forward not) stays banned; a DNS doubt is never an exemption. Bans already placed on verified robots are lifted at startup. The check needs the AppArmor profile to allow DNS, which the package reloads on upgrade.

Per-vhost anti-robots

Vhosts listed in anti_robots (/etc/secubox/waf/vhost_profiles.json, ticked with the Anti-robots checkbox of the Vhost panel) refuse search and harvesting robots with HTTP 403 (not 429: "come back later" would invite retries). It is a load decision, not threat detection: no ban, logged apart with action=robot. An empty list filters nobody. Three paths are always served: /robots.txt, /favicon.ico, /.well-known/. The LAN is exempt.

Decoys, honeypot and watermark

With --honeypot (off by default; example drop-in shipped in /usr/share/secubox/waf/honeypot.conf), unrouted host names and bait paths of real vhosts (/.env, /.git/…) are answered by a decoy. A decoy has no other purpose than detecting: any contact is banned, except the LAN and protected ranges.

Everything the decoy hands out carries a watermark: random bytes followed by an HMAC-SHA256 tag. Our marks are recognised anywhere without a table, nobody can forge one, and a fake key replayed against a real service earns a ban of at least 24 h. The secret lives in /etc/secubox/secrets/filigrane.

Beyond HTTP: sbx-authwatch

sbx-authwatch reads SSH, SMTP and IMAP (journal and files) and writes into the same ban set and the same threat log: campaign detection (keyed on the targeted account), non-existent account detection, 10 decoy ports that record and stay quiet. Per-service filters in /etc/secubox/authwatch/services.json; a service without a verified pattern stays "actif": false with the reason written down.

Threat log and permissions

Item Value
Threat log /var/log/secubox/waf/waf-threats.log
Directory and file owner secubox-waf, directory 0750, rule enforced at each boot by tmpfiles
State /var/lib/secubox/waf/ (bans.jsonl, reevaluations.jsonl, …)
Decision audit /var/log/secubox/waf/audit.log (the central audit.log is closed to secubox-waf)

The service runs as the dedicated user secubox-waf (AppArmor enforce). The package re-applies the ownership at each start: a directory created by another component must not lock the WAF out of its own log.

Declarative routes

A vhost unknown to sbxwaf gets a 421. The route table is /etc/secubox/waf/haproxy-routes.json, hot-reloaded. A package declares its route in its postinst — never by hand:

secubox-waf-route app.exemple.test 9080

The only sanctioned bypass is declarative: waf_bypass = true per vhost in /etc/secubox/haproxy.toml, honoured by haproxyctl.

Main API (/api/v1/waf/…)

Route Use
GET stats, alerts, history, campaigns, visits, detections data of the admin views (read)
GET bans, bans/history, enforcement, enforcement/mode, decisions, reevaluations bans and decisions (read)
POST ban, POST unban/{ip}, POST enforcement/{id}/rollback actions (administrator)
GET doctor, POST repair, POST reload health and repair

See also

SOC · Actor-Intelligence · ThreatMesh · Anti-Track · DPI-Vivant · Architecture · WAF-FR

⚠️ **GitHub.com Fallback** ⚠️