140 lines
5 KiB
Markdown
140 lines
5 KiB
Markdown
# 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 URL** | `http://127.0.0.1:8080` | The firewall application itself (e.g., Wallarm, ModSecurity, Coraza) |
|
||
| **Return Port** | `8080` | Port where inspected traffic returns to Zoraxy for routing |
|
||
| **Health Interval** | `5s` | How often to check if the WAF is reachable |
|
||
| **Timeout** | `500ms` | Max wait time for an inspection verdict |
|
||
|
||
---
|
||
|
||
## How It Works
|
||
|
||
```
|
||
Client → Zoraxy → Plugin → http://waf:8080 [Firewall App] → inspect
|
||
│
|
||
┌────┴──────────┐
|
||
│ 403 → BLOCK │
|
||
│ 2xx → RETURN │──→ Zoraxy (port 8080) → Backend
|
||
│ down → FAIL-OPEN│──→ Zoraxy routes directly
|
||
└───────────────┘
|
||
```
|
||
|
||
1. Zoraxy proxies traffic to the firewall application at the configured WAF URL
|
||
2. The firewall app inspects the request inline
|
||
3. If blocked (403), the plugin drops the request
|
||
4. If allowed (2xx), traffic returns to Zoraxy on the return port for routing to the final backend
|
||
5. If the firewall app is unreachable, the circuit breaker opens and traffic bypasses inspection (fail-open)
|
||
|
||
### 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 firewall application responds, the circuit breaker records success. If unreachable, it records a failure.
|
||
|
||
---
|
||
|
||
## Inspection Protocol
|
||
|
||
The plugin proxies the full HTTP request to the WAF URL. The firewall application inspects it inline and returns an HTTP status code:
|
||
|
||
- **200–299** → Traffic is clean, returned to Zoraxy for routing
|
||
- **403** → Request is malicious, plugin blocks it
|
||
- **5xx / timeout** → Plugin fails open, breaker records failure
|
||
|
||
Any firewall application that accepts proxied HTTP traffic and returns a status code is compatible.
|
||
|
||
---
|
||
|
||
## 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)
|