synapse-waf 0.9.0

High-performance WAF and reverse proxy with embedded intelligence — built on Cloudflare Pingora
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
# Synapse WAF PoC

A proof-of-concept integrating the **real Synapse WAF detection engine** (237 production rules) with Cloudflare's [Pingora](https://github.com/cloudflare/pingora) proxy framework. **Pure Rust, no Node.js, no FFI boundary**.

## Performance Headlines

| Metric | Result |
|--------|--------|
| **Clean GET** | **~10 μs** |
| **Attack detection** | **~25 μs** avg across all vectors |
| **Full pipeline (WAF + DLP, 4 KB)** | **~247 μs** |
| Rules loaded | **237** production rules |
| Benchmark suites | **19** suites, **306** benchmarks |
| vs NAPI (Node.js FFI) | **~2-3x faster** |
| vs ModSecurity | **4-19x faster** |

> **Note**: February 2026 Criterion.rs numbers on macOS arm64. See
> [`docs/performance/BENCHMARK_REPORT_2026_02.md`]docs/performance/BENCHMARK_REPORT_2026_02.md for the full report.

## Architecture

### Pingora Approach (This PoC)

```mermaid
flowchart LR
    Client -->|request| SP["Synapse WAF<br/><b>Single Binary</b>"]
    SP -->|proxy| Backend[Backend Server]
    Backend -->|response| SP
    SP -->|response| Client

    subgraph SP_inner [" "]
        direction TB
        Engine["libsynapse (in-proc)<br/>237 Rules · Entity Tracking · Risk Scoring"]
    end

    style SP fill:#1e40af,color:#fff
    style Engine fill:#2563eb,color:#fff
    style Client fill:#f8fafc,stroke:#334155
    style Backend fill:#f8fafc,stroke:#334155
```

### Current Approach (nginx + Node.js)

```mermaid
flowchart LR
    Client -->|request| Nginx[nginx]
    Nginx -->|subrequest| RS["risk-server<br/>(Node.js)"]
    RS -->|verdict| Nginx
    Nginx -->|proxy| Backend[Backend Server]

    RS --- NAPI["NAPI Bridge"]
    NAPI --- Lib["libsynapse<br/>(Rust FFI)"]

    style Nginx fill:#dc2626,color:#fff
    style RS fill:#dc2626,color:#fff
    style NAPI fill:#b91c1c,color:#fff
    style Lib fill:#991b1b,color:#fff
    style Client fill:#f8fafc,stroke:#334155
    style Backend fill:#f8fafc,stroke:#334155
```

> **3 components + FFI overhead** vs a single Rust binary.

**Key difference**: Detection happens *inside* the proxy, not across a process boundary.

## Quick Start

```bash
# Build release binary
cargo build --release

# Run (uses default config)
./target/release/synapse-waf

# Run with interactive TUI dashboard
./target/release/synapse-waf --tui

# Or with config file
cp config.example.yaml config.yaml
./target/release/synapse-waf

# Run integration tests
./test.sh
```

## Benchmark Results (February 2026)

Criterion.rs results from 19 benchmark suites (306 benchmarks), release build with LTO:

### Detection Engine

| Benchmark | Latency | Notes |
|-----------|---------|-------|
| **Simple GET** | **10.0 μs** | Minimal GET, no params |
| **SQLi detection** | **26.6 μs** | Average across 5 SQLi variants |
| **XSS detection** | **23.3 μs** | Average across 3 XSS variants |
| **Evasive attacks** | **25-33 μs** | Hex, double-encoding, unicode, polyglot |
| **Full rule set (237)** | **71.6 μs** | Linear scaling, ~302 ns/rule |

### Per-Request Hot Path

| Operation | Latency |
|-----------|---------|
| Rate limit check | 61 ns |
| ACL evaluation (100 rules) | 156 ns |
| Trap matching (honeypot) | 33 ns |
| Actor is-blocked check | 45 ns |
| Session validation | 304 ns |

### End-to-End Pipeline

| Scenario | Latency |
|----------|---------|
| Clean GET, full chain | 72 μs |
| WAF + DLP (4 KB body) | 247 μs |
| WAF + DLP (8 KB body) | 442 μs |
| E-commerce order (heavy) | 1.6 ms |
| Healthcare claim (PII + DLP) | 2.3 ms |

### Comparison

| Implementation | Detection Latency | Notes |
|----------------|-------------------|-------|
| **Synapse WAF** | **~10-25 μs** | Pure Rust, no FFI boundary |
| libsynapse (NAPI) | ~62-73 μs | Node.js + Rust FFI overhead |
| ModSecurity | 100-500 μs | Depends on ruleset |
| AWS WAF | 50-200 μs | Cloud service |

### Value Proposition

Pingora eliminates the **~47 μs FFI overhead** (73 μs NAPI vs 25 μs pure Rust), providing
a **~2-3x speedup** over the Node.js architecture:

1. **Simpler architecture** - Single Rust binary vs nginx + Node.js + NAPI stack
2. **No serialization boundary** - Detection runs in-process, no IPC
3. **No GC pauses** - No V8 heap, predictable latency
4. **Graceful reload** - Zero-downtime updates via SIGQUIT + socket handoff
5. **Thread-local engines** - Each Pingora worker has its own Synapse instance

| Metric | Current (nginx + NAPI) | Pingora | Improvement |
|--------|------------------------|---------|-------------|
| Per-request latency | ~73 μs | ~25 μs | **~3x faster** |
| Components to deploy | 3 (nginx, Node.js, NAPI) | 1 binary | **Simpler** |
| Memory footprint | Node.js + V8 heap | Rust only | **~50% smaller** |
| Cold start | Seconds (V8 init) | Milliseconds | **Much faster** |
| Config reload | Service restart | 240 μs hot reload | **Zero downtime** |

## Configuration

Copy `config.example.yaml` to `config.yaml`:

```yaml
# Server settings (flat fields on GlobalConfig)
http_addr: "0.0.0.0:80"
https_addr: "0.0.0.0:443"
workers: 0                    # 0 = auto-detect CPU count
shutdown_timeout_secs: 30
waf_threshold: 70             # Global risk threshold (0-100)
waf_enabled: true
log_level: "info"             # trace, debug, info, warn, error
waf_regex_timeout_ms: 100     # ReDoS protection (max 500)
# admin_api_key: "..."        # Optional; random key generated if unset

# Upstream backends (round-robin)
upstreams:
  - host: "127.0.0.1"
    port: 8080

# Rate limiting
rate_limit:
  rps: 10000
  enabled: true

# Detection toggles
detection:
  sqli: true
  xss: true
  path_traversal: true
  command_injection: true
  action: "block"             # block, log, challenge
  block_status: 403
```

See [`docs/reference/configuration.md`](docs/reference/configuration.md) for the full reference.

## Pingora Hooks Used

| Hook | Purpose |
|------|---------|
| `early_request_filter` | Rate limiting (pre-TLS) |
| `request_filter` | Attack detection (main filter) |
| `request_body_filter` | DLP body inspection (PII/sensitive data scanning) |
| `upstream_peer` | Round-robin backend selection |
| `upstream_request_filter` | Add `X-Synapse-*` headers |
| `logging` | Access logs with timing |

## Integration Tests

Run the test script to verify everything works:

```bash
# With proxy already running
./test.sh

# Or start proxy, run tests, stop proxy
./test.sh --start
```

Sample output:

```
============================================
  Synapse WAF Integration Tests
============================================

[INFO] Testing clean requests (should PASS)...
[PASS] Simple GET / (502 - allowed)
[PASS] API endpoint (502 - allowed)
...

[INFO] Testing SQL injection (should BLOCK)...
[PASS] SQLi: OR condition (403) - 2ms
[PASS] SQLi: UNION SELECT (403) - 1ms
...

============================================
  Results: 23/23 passed
============================================

All tests passed!
```

## Configuration Hot-Reload

Synapse supports zero-downtime configuration updates via the admin API:

```bash
# Reload configuration (~240 μs atomic swap, no dropped requests)
curl -X POST http://localhost:6191/reload -H "X-Admin-Key: $ADMIN_KEY"
```

How it works:

1. New config is parsed and validated
2. Routing table and WAF rules are rebuilt
3. Atomic `RwLock` swap replaces the live config
4. In-flight requests continue unaffected

## Graceful Shutdown

The process handles `SIGQUIT`, `SIGTERM`, and `SIGINT` for graceful shutdown:

1. Signal received — stop accepting new connections
2. In-flight requests are allowed to complete (draining)
3. Process exits when all connections are closed

## Building

```bash
# Development build
cargo build

# Release build (optimized)
cargo build --release

# With full optimizations (LTO + native CPU)
RUSTFLAGS="-C target-cpu=native" cargo build --release

# Run tests
cargo test

# Run benchmarks
cargo bench
```

## Example Usage

### Clean Request (Allowed)

```bash
curl -v http://localhost:6190/api/users/123
# → Proxied to backend
# → X-Synapse-Analyzed: true
# → X-Synapse-Detection-Time-Us: 1
```

### SQL Injection (Blocked)

```bash
curl -v "http://localhost:6190/api/users?id=1'+OR+'1'%3D'1"
# → HTTP 403 Forbidden
# → {"error": "blocked", "reason": "sqli"}
```

### XSS (Blocked)

```bash
curl -v "http://localhost:6190/search?q=%3Cscript%3Ealert(1)%3C/script%3E"
# → HTTP 403 Forbidden
# → {"error": "blocked", "reason": "xss"}
```

### POST with Body

```bash
curl -v -X POST -d '{"user":"test"}' http://localhost:6190/api/users
# Body size logged: "Request body complete: 15 bytes"
```

## Upstream Headers

The proxy adds these headers to upstream requests:

| Header | Description |
|--------|-------------|
| `X-Synapse-Analyzed` | Always "true" |
| `X-Synapse-Detection-Time-Us` | Detection time in microseconds |
| `X-Synapse-Client-IP` | Client IP (from X-Forwarded-For or connection) |

## Detection Engine

This PoC uses the **real libsynapse engine** from `../risk-server/libsynapse/`, which includes:

- **237 production rules** covering SQLi, XSS, path traversal, command injection, and more
- **Behavioral tracking** - Entity risk accumulates across requests from the same IP
- **Risk scoring** - Graduated risk levels (0-100) with configurable blocking thresholds
- **Rule chaining** - Multiple rules can match and contribute to overall risk

### Verified Detections

Tested and verified to block:

- `UNION SELECT` SQLi attacks (rule 200200)
- Path traversal attempts (rules 200014, 200016)
- Various other attack patterns from the production rule set

### Rules Loading

Rules are loaded at startup from (in order of preference):

1. `../risk-server/libsynapse/rules.json` (production rules)
2. `rules.json` (local override)
3. `/etc/synapse-pingora/rules.json` (system-wide)
4. `src/minimal_rules.json` (fallback with 7 basic patterns)

## Performance Optimizations

1. **Thread-local engines**: Each Pingora worker has its own Synapse instance
2. **Lazy rule loading**: Rules parsed once at startup via `once_cell::Lazy`
3. **Zero-copy headers**: Header references passed directly to engine
4. **LTO**: Link-time optimization in release builds (profile: fat LTO, 1 codegen unit)
5. **Native CPU**: Build with `RUSTFLAGS="-C target-cpu=native"` for best performance

### DLP Body Inspection Optimizations

The DLP scanner has been optimized for high-throughput request body scanning:

| Optimization | Description | Impact |
|--------------|-------------|--------|
| **Content-Type Short Circuit** | Skip binary types (image/*, video/*, multipart/form-data) | Eliminates scan overhead for file uploads |
| **Inspection Depth Cap** | Truncate body to first 8KB by default | O(1) scan time for large payloads |
| **Aho-Corasick Prefilter** | Single-pass multi-pattern detection | 30-50% faster than sequential regex |

#### DLP Performance Benchmarks (February 2026)

| Payload Size | With PII | Clean Traffic | Notes |
|--------------|----------|---------------|-------|
| 4 KB | **~34 μs** | ~21 μs | E-commerce order payloads |
| 8 KB | ~65 μs | ~42 μs | At inspection cap limit |
| 18 KB | ~68 μs | ~42 μs | Truncated to 8KB cap |
| 32 KB | ~64 μs | ~41 μs | Plateaus due to truncation |

DLP fast mode saves 30-34%: 4 KB drops from ~34 μs to ~24 μs, 8 KB from ~70 μs to ~46 μs.

#### DLP Configuration Options

```rust
// In code (DlpConfig)
DlpConfig {
    enabled: true,                        // Enable/disable DLP scanning
    max_scan_size: 5 * 1024 * 1024,       // 5MB hard limit (reject if larger)
    max_matches: 100,                     // Stop after 100 matches
    scan_text_only: true,                 // Only scan text content types
    max_body_inspection_bytes: 8 * 1024,  // 8KB inspection cap (truncate, don't reject)
}
```

**Tuning Recommendations**:

- **High-security environments**: Set `max_body_inspection_bytes` to 32KB+ for deeper inspection
- **High-throughput APIs**: Keep default 8KB cap for sub-100μs scan times
- **File upload endpoints**: Binary content types are automatically skipped

#### Content Types Automatically Skipped

- `image/*` - All image formats
- `audio/*` - All audio formats
- `video/*` - All video formats
- `application/octet-stream` - Binary data
- `multipart/form-data` - File uploads
- `application/zip`, `application/gzip`, etc. - Archives
- `font/*` - Font files
- `model/*` - 3D models

## Future Work (For Feature Parity with nginx)

### Core Features (Required for Production)

- [x] Full detection rule parity with libsynapse (DONE - using real engine)
- [x] **Multi-site/vhost support** - Hostname-based routing with per-site config
- [x] **TLS termination** - SSL certificates, SNI support
- [x] **Health check endpoint** - `/_sensor/status` equivalent
- [x] **Per-site WAF config** - Override rules, thresholds per hostname

### Management Features (Important)

- [x] **Metrics endpoint** - Prometheus-compatible `/metrics`
- [x] **Config hot-reload API** - Update config without restart
- [x] **Access lists** - Allow/deny CIDRs per site
- [x] **Per-site rate limiting** - Hostname-aware rate limits
- [x] Signal Horizon telemetry integration

### Advanced Features

- [x] DLP scanning in `request_body_filter` (DONE - with performance optimizations)
- [x] Request body inspection (POST/PUT payloads) (DONE - with truncation cap)
- [x] Custom block pages per site
- [x] Dashboard UI integration (Dashboard compatibility routes)
- [x] Production hardening (security audit remediations complete)

## Files

```
synapse-pingora/
├── Cargo.toml              # Dependencies
├── config.example.yaml     # Example configuration
├── test.sh                 # Integration test script
├── README.md
├── benches/
│   └── detection.rs        # Criterion benchmarks
├── assets/
│   └── admin_console.html  # Embedded admin web console
├── docs/                   # Project documentation
│   ├── reference/          # Configuration reference
│   ├── tutorials/          # Tuning, DLP, shadow mirroring
│   └── api/                # Admin API reference
└── src/
    ├── main.rs             # Binary entrypoint + Pingora proxy impl
    ├── lib.rs              # Library crate root
    ├── config.rs           # YAML config loading & validation
    ├── admin_server.rs     # Admin HTTP API (90+ endpoints)
    ├── api.rs              # API handler traits
    ├── metrics.rs          # Prometheus metrics registry
    ├── health.rs           # Health check logic
    ├── rules.rs            # Rule loading & management
    ├── tui.rs              # Interactive terminal dashboard
    ├── waf/                # WAF detection engine
    ├── entity/             # IP/actor entity store & risk tracking
    ├── actor/              # Behavioral actor tracking
    ├── session/            # Session tracking & hijack detection
    ├── detection/          # Credential stuffing & login detection
    ├── correlation/        # Campaign correlation engine
    ├── intelligence/       # Signal intelligence manager
    ├── dlp/                # Data Loss Prevention scanner
    ├── profiler/           # Endpoint profiling & schema learning
    ├── payload/            # Bandwidth & payload analysis
    ├── trends/             # Trend analysis & anomaly detection
    ├── fingerprint/        # JA4 fingerprinting & integrity
    ├── crawler/            # Bot & crawler detection
    ├── geo/                # GeoIP & impossible travel detection
    ├── shadow/             # Shadow traffic mirroring
    ├── signals/            # Signal adapter layer
    ├── horizon/            # Signal Horizon hub integration
    ├── tunnel/             # Secure tunnel client
    ├── telemetry/          # Telemetry & reporting
    ├── interrogator/       # CAPTCHA, JS challenge, cookie mgmt
    ├── persistence/        # State persistence layer
    ├── tarpit/             # Tarpit (not shown: src/tarpit/)
    ├── utils/              # Circuit breaker & shared utilities
    └── (14 more modules)   # access, block_log, block_page, body,
                            # config_manager, headers, ratelimit,
                            # reload, shutdown, site_waf, sni_validation,
                            # tls, trap, validation, vhost
```

## License

Licensed under the GNU Affero General Public License v3.0 only.
Copyright Nicholas Crew Ferguson
See [LICENSE](../../LICENSE).

## See Also

- [Pingora GitHub]https://github.com/cloudflare/pingora
- [Pingora Documentation]https://docs.rs/pingora