Skip to content

feat!: rewrite the backend in Rust (remove Go) - #80

Merged
zulfff merged 3 commits into
mainfrom
feat/rust-backend
Sep 29, 2026
Merged

zulfff merged 3 commits into
mainfrom
feat/rust-backend

Conversation

@zulfff

@zulfff zulfff commented Sep 29, 2026

Copy link
Copy Markdown
Contributor

Summary

Replaces the Go backend with a Rust cargo workspace under rust/, and removes the Go implementation entirely. The Dockerfile, Makefile, CI workflows, install.sh, and pre-commit config now build and lint Rust.

The whole product is five crates:

Crate Contents
core request model, Engine pipeline, all 25 inspectors
config YAML config: defaults, validation, hot reload
services ratelimit, blocklist, session, geo, reputation, siem, ml, tenant, sites, billing, compliance, traincorpus, uaparse
proxy WAF pipeline, admin API, TLS, hyper servers, fortresswaf binary
ctl fortressctl CLI + healthcheck

Behaviour

Preserved, not reinterpreted: rule IDs, scores, decision ordering, threshold semantics, and config defaults match the original. Several original bugs are reproduced on purpose (documented in rust/DEVIATIONS.md). Detection parity is enforced by rust/crates/proxy/tests/attack_corpus.rs, which replays the training corpus and fails the build if any category drops below its documented floor, with zero false positives on the benign corpus.

TLS termination is implemented with rustls (cert/key, min version, optional mTLS, ALPN http/1.1). Prometheus /metrics is served on its own listener. ACME auto-provisioning is the one remaining gap, called out in the README.

Verification (measured locally)

  • cargo test --workspace --locked — 288 passed, 0 failed
  • cargo clippy --workspace --all-targets --locked -- -D warnings — clean
  • cargo fmt --check — clean
  • cargo build --release --locked — clean (fortresswaf, fortressctl, healthcheck)
  • Live smoke test: HTTPS request blocked with 403 + X-FortressWAF-Rule: SQLI016; admin /health 200; authenticated /api/v1/status 200

Detection rates replay to the documented floors: XXE 100%, XSS 99.3%, deserialization 97.1%, webshell 80%, path-traversal 86.7%, SQLi 67.3%.

Removed

cmd/, internal/, tests/*.go, tools/, go.mod, go.sum, .golangci.yml, benchmark.txt.

tests/attack-corpus/ is kept — the parity test consumes it.

Breaking change

The backend is now Rust; the Go module and its toolchain are gone.

FortressWAF Dev added 3 commits September 29, 2026 12:23
A per-IP flood (DDoS001) now bans the source address for ddos.ban_seconds
(default 10m), and an address that keeps producing bot-like requests is banned
too. Bans are time-limited, reversible, logged, and raise an alert; loopback and
trusted-proxy addresses are never auto-banned. The ban request survives into the
final decision — a high accumulated score used to turn a flood into a plain
challenge and drop the ban.

Missing User-Agent (BOT001) is now challenged instead of only monitored. DDoS
and bot thresholds are configurable, and a negative ban value disables auto-ban.

The client IP is read from CF-Connecting-IP when the peer is a trusted proxy, so
behind Cloudflare the WAF sees the real visitor rather than the Cloudflare edge;
rate limits, auto-bans, and the audit log are accurate.

Verified live: a 40-request burst through the public host banned the source with
"DDoS001 HTTP Flood - IP" for 10m and surfaced it in /api/v1/bans.
The API base is now the relative "/api/v1", so new URL() threw and the CSP
became "connect-src 'self' /api/v1" — a path is not a valid CSP source, so the
browser logged an error and ignored it. Only add an origin when the base is an
absolute URL; a relative base is covered by 'self'.
Replaces the Go backend (cmd/, internal/) with a cargo workspace under
rust/ containing the whole product as five crates: core (detection engine
and all 25 inspectors), config (YAML with defaults, validation, hot
reload), services (ratelimit, blocklist, session, geo, reputation, siem,
ml, tenant, sites, billing, compliance, traincorpus, uaparse), proxy
(WAF pipeline, admin API, TLS, hyper servers, binary), and ctl (fortressctl
+ healthcheck).

Behaviour is preserved, not reinterpreted: rule IDs, scores, decision
ordering, threshold semantics, and config defaults match, and several
original bugs are reproduced on purpose. Detection parity is enforced by
rust/crates/proxy/tests/attack_corpus.rs, which replays the training
corpus and fails if any category drops below its documented floor, with
zero false positives on the benign corpus.

TLS termination is implemented with rustls (cert/key, min version, optional
mTLS, ALPN http/1.1). Prometheus /metrics is served on its own listener.
Every intentional difference is documented in rust/DEVIATIONS.md.

Build infrastructure is now Rust end to end: Dockerfile (rust:1-slim ->
distroless), Makefile, all GitHub Actions workflows (ci, benchmark,
release, security), install.sh, and .pre-commit-config.yaml (cargo fmt +
cargo clippy).

Verification (measured):
- cargo test --workspace --locked: 288 passed, 0 failed
- cargo clippy --workspace --all-targets --locked -- -D warnings: clean
- cargo fmt --check: clean
- cargo build --release --locked: clean (fortresswaf, fortressctl, healthcheck)
- live: HTTPS request blocked with 403 + X-FortressWAF-Rule: SQLI016

Removed: cmd/, internal/, tests/*.go, tools/, go.mod, go.sum, .golangci.yml,
benchmark.txt. tests/attack-corpus/ is kept (consumed by the parity test).

BREAKING CHANGE: the backend is now Rust; the Go module and its toolchain
are gone.
@zulfff
zulfff merged commit f8a683b into main Sep 29, 2026
6 checks passed
@zulfff

zulfff commented Sep 29, 2026

Copy link
Copy Markdown
Contributor Author

Added AGENTS.md and skills/fortresswaf-rust-backend — agent instructions for this repo. Rust jobs unaffected (docs-only commit).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant