Commit Graph

3 Commits

Author SHA1 Message Date
shadowdao 1b557b9931 feat(waf): wp-login cookie challenge (defeats distributed credential-stuffing)
HAProxy Manager Build and Push / Build-and-Push (push) Successful in 1m29s
The per-IP throttle can't see distributed attacks (observed 76k–289k UNIQUE
IPs hitting wp-login.php, each low-and-slow). But those bots POST straight to
wp-login.php without GETting the form (~15:1 POST:GET on attacked sites). So:
hand out a `whplc` cookie on GET of the login form (set-var at request time +
http-after-response add-header — request fetches don't evaluate in the response
phase) and DENY 403 on login POSTs that lack it. Direct-POST bots are dropped
at the edge before reaching PHP; real logins are unaffected (WP login already
requires loading the page + cookies). Immediate deny, not tarpit, to avoid
connection exhaustion under a 300k-POST flood. Honors the whitelist.

Validated locally: GET /wp-login.php emits whplc; other paths don't; config OK.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-24 20:30:12 -07:00
shadowdao 6ced2f8797 feat(waf): edge brute-force throttle for wp-login.php
HAProxy Manager Build and Push / Build-and-Push (push) Successful in 2m8s
The generic rate-limits are tuned high for media-heavy sites, so slow
credential-stuffing on wp-login.php slips under them. Add a dedicated sc1
stick-table (backend wp_bruteforce, 60s window) that counts POSTs to
wp-login.php per real client IP and tarpits once an IP exceeds 30/min.

Only login POSTs are counted (browsing + the login form GET + a legit user's
few attempts are unaffected); an offending IP can still browse, just not keep
hammering login. Honors the existing whitelist (RFC1918 / trusted_ips.list /
trusted_ips.map) and the already-resolved CF/proxy real IP. path_end also
covers subdirectory WP installs. Stops attacks at the edge before they reach
PHP/WordPress, on all edges regardless of Coraza mode.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-24 19:52:52 -07:00
shadowdao d9cc5311de feat(quic): enable HTTP/3 over QUIC on the edge + versioned images
HTTP/3 is config-only — the Debian haproxy package is built +QUIC via the
OpenSSL compat shim. Changes:
- hap_header.tpl: `limited-quic` (required to enable QUIC binds under the
  compat layer) + self-healing `cluster-secret` for QUIC token derivation.
- hap_listener.tpl: `bind quic4@:443 ... alpn h3` in the shared frontend (so
  real-IP/rate-limit/IP-block/Coraza rules apply to H3 too) + alt-svc header.
- Dockerfile/README: publish/document 443/udp; stamp image.version from VERSION.
- CI: tag :latest + :<VERSION> + :<sha> so there's a pinnable rollback target.

No 0-RTT (compat-layer limitation). Validated end-to-end on a standalone edge:
config parses, UDP/443 binds, alt-svc advertised, real curl --http3 -> HTTP/3.
Container must run with `-p 443:443/udp` + host UDP/443 open.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-24 13:40:11 -07:00