diff --git a/README.md b/README.md new file mode 100644 index 0000000..65b5789 --- /dev/null +++ b/README.md @@ -0,0 +1,154 @@ +# Firewall + +**Zoraxy plugin** — Inline WAF inspection proxy with health checks, circuit breaker, and fail-open bypass. Works with Wallarm, ModSecurity, Coraza, or any inspection service that returns HTTP status codes. + +--- + +## Quick Install + +The plugin is built into Zoraxy — just enable it from the Plugins panel. If you need to build from source: + +```bash +git clone https://git.lohmar.co.uk/cclohmar/zoraxy-waf.git /opt/zoraxy/plugins/zoraxy-waf +cd /opt/zoraxy/plugins/zoraxy-waf +go build -buildvcs=false -o zoraxy-waf . +chown -R zoraxy:zoraxy /opt/zoraxy/plugins/zoraxy-waf +systemctl restart zoraxy +``` + +Then enable **Firewall** in Zoraxy → Plugins. + +--- + +## Configuration + +Open the Firewall panel at `/plugin.ui/zoraxy-firewall/`: + +| Setting | Default | Description | +|---------|---------|-------------| +| **Enable** | Off | Toggle WAF inspection on/off | +| **WAF Inspection URL** | `http://127.0.0.1:8080` | Inspection endpoint — receives `POST /inspect` | +| **Return Port** | `8080` | Port for async WAF callbacks/alerts | +| **Health Interval** | `5s` | How often to ping the WAF | +| **Timeout** | `500ms` | Max wait time for a verdict | + +--- + +## How It Works + +``` +Client → Zoraxy + │ + ▼ + ┌──────────────────┐ + │ Firewall Plugin │──► POST http://waf:8080/inspect + │ (static capture) │ {method, url, headers, body_sample} + └────┬─────────────┘ + │ + ┌────┴────────────────────────────┐ + │ WAF returns 403 │ → 280 (BLOCK) → Request dropped + │ WAF returns 2xx │ → 284 (FORWARD) → Zoraxy routes to backend + │ WAF unreachable / breaker OPEN │ → 284 (FAIL-OPEN)→ Zoraxy routes to backend + └─────────────────────────────────┘ +``` + +### Circuit Breaker + +If the WAF fails 5 times within a 30-second window, the breaker opens. All traffic bypasses inspection (fail-open) for 10 seconds. After the cooldown, the next successful health check closes the breaker. + +### Health Check + +The plugin periodically sends a `HEAD` request to the WAF URL. If the WAF responds with < 500, the circuit breaker records success. If it fails or returns 5xx, it records a failure. + +--- + +## Inspection Protocol + +The plugin sends this JSON payload to `{WAF_URL}/inspect`: + +```json +{ + "method": "GET", + "url": "/some/path", + "host": "example.com", + "remote_addr": "10.1.0.5:12345", + "content_type": "application/json", + "content_length": 256, + "headers": {...}, + "body_sample": "" +} +``` + +The WAF inspects and returns an HTTP status code: +- **200–299** → Request is clean, Zoraxy forwards to backend +- **403** → Request is malicious, plugin blocks it +- **5xx / timeout** → Plugin fails open, records breaker failure + +Any WAF that accepts a POST and returns the appropriate status code is compatible. No special Wallarm integration required. + +--- + +## Zoraxy Integration + +To activate the plugin for specific proxy rules: + +1. Zoraxy → Plugins → enable **Firewall** +2. Create a plugin group (e.g., "waf") → add the Firewall plugin +3. Edit proxy rules → add the "waf" tag + +The plugin uses Zoraxy's **static capture** to intercept all requests matched by tagged proxy rules. + +--- + +## API Endpoints + +| Method | Path | Purpose | +|--------|------|---------| +| `GET` | `/ui/api/config` | Get current configuration | +| `POST` | `/ui/api/config/save` | Save configuration | +| `GET` | `/ui/api/stats` | Inspect/bock/bypass metrics + breaker state | +| `POST` | `/inspect` | Static capture — Zoraxy sends traffic here | +| `POST` | `/verdict` | Return port — WAF sends async callbacks here | + +--- + +## Architecture + +``` +/opt/zoraxy/plugins/zoraxy-waf/ +├── zoraxy-waf # Compiled plugin binary +├── waf_config.json # Runtime configuration (auto-created) +├── config.go # Config load/save (thread-safe) +├── main.go # Plugin entry, UI router, return listener +├── middleware.go # Inspection handler + metrics +├── proxy.go # WAF HTTP client (body sample + request forwarding) +├── circuit_breaker.go # Fail-open state machine +├── health.go # Background health check goroutine +├── web/ # Config panel UI +│ ├── index.html +│ ├── style.css +│ └── app.js +├── cmd/mockwallarm/ # Test mock WAF server +└── zoraxy_plugin/ # Vendored Zoraxy plugin SDK (LGPL) +``` + +--- + +## Environment Variables + +| Variable | Default | Description | +|----------|---------|-------------| +| *none* | — | All config is managed through the UI and persisted to `waf_config.json` | + +--- + +## License + +Zoraxy plugin SDK is LGPL. This plugin is open source. + +--- + +## Credits + +- [Zoraxy](https://github.com/tobychui/zoraxy) — Reverse proxy and plugin system +- Compatible with any WAF that returns HTTP verdicts (Wallarm, ModSecurity, Coraza, custom)