Web Application Firewall (WAF)¶
A self-hosted, Cloudflare-style gateway in front of internal web apps. Every public request to a protected site passes through the WAF, which decides whether to forward it to the app's origin (a Kubernetes ingress, IIS or any HTTP service). Origins accept traffic only from the WAF.
What it does per request¶
| Check | Technology | Notes |
|---|---|---|
| TLS termination, routing by hostname | HAProxy | One public address for many apps; the app is decided by the WAF's own host map, never by a client header |
| Country and ASN policy | GeoLite2 maps | Per app: allow list, deny list or off; action block or log |
| IP reputation | CrowdSec | Community blocklist plus local detections |
| Manual IP bans and allows | Control plane → HAProxy maps | Global or per app, with optional expiry; live within seconds |
| Known bots | Vendor IP ranges + ai.robots.txt | Verified / spoofed / unverified search bots, AI crawler categories, per-app allow/log/block |
| Rate limiting | HAProxy stick tables | Per source IP and app |
| OWASP rules | Coraza with the OWASP Core Rule Set | Per app detect or block mode, paranoia level, exclusions |
| Header control | HAProxy | Client-supplied X-Client-*, X-WAF-*, X-Bot-*, X-Forwarded-* headers are always stripped, then set by the WAF |
| Logging | HAProxy JSON log | One line per request with app, country, ASN, bot fields, WAF action, rule IDs, TLS fingerprints |
Architecture¶
flowchart LR
I[Internet] -->|public address| O[Firewall<br/>NAT + BGP]
O -->|VIP| N[WAF nodes<br/>HAProxy + Coraza + CrowdSec]
N -->|allowed requests| K[Origins<br/>k8s ingress / IIS]
N <-->|Runtime API| CP[Control plane<br/>GUI + API + Postgres]
CP -->|triggers deploys| G[CI pipeline<br/>Ansible]
G -->|SSH| N
- Data plane: HAProxy with the Coraza SPOA (OWASP rules) and the CrowdSec bouncer on each WAF node. The public address is NATed by the edge firewall to a virtual IP (VIP), which the WAF nodes announce to the firewall over BGP.
- Control plane: a web GUI and API backed by Postgres, the source of truth for apps, origins and policies. It pushes instant changes (bans, WAF mode, geo/ASN and bot policy) straight to the nodes through the HAProxy Runtime API, and triggers CI pipelines for structural changes.
- Deploys: Ansible, run from CI. Every config is validated with
haproxy -cbefore it goes live, nodes are updated one at a time, and a failed deploy restores the previous config.
In this section¶
- Operations: day-to-day use, deploys, certificates, bans, logs
- Network and BGP: the VIP, BGP peering, active/passive failover, draining a node
- Security model: access control, secrets, hardening, failure behaviour
- Troubleshooting: common problems and the commands to diagnose them
Environment-specific values (addresses, AS numbers, hostnames) live in the WAF repository's inventory and runbook, not here.