mirror of
https://github.com/fabriziosalmi/caddy-waf.git
synced 2026-07-30 14:25:56 -04:00
Full rewrite of README.md, MODULE.md, caddyfile.example, and docs/ to match the actual code in caddywaf.go, handler.go, config.go, rules.go, ratelimiter.go, blacklist.go, geoip.go, request.go, and types.go. Notable corrections: - docs/configuration.md now lists every directive recognised by the Caddyfile parser (directiveHandlers in config.go) and separates JSON-only fields (MaxRequestBodySize, GeoIPFailOpen, Tor.CustomTORExitNodeURL). - docs/rules.md documents the JSON tag mismatch on Rule.Action: the struct tag is "mode" while the bundled rule files commonly use "action". - docs/ratelimit.md corrects the match_all_paths semantics to match ratelimiter.go (true rate-limits all paths; false + non-empty paths rate-limits only matching paths; false + empty paths is a no-op). - docs/dynamicupdates.md adds a reload matrix distinguishing what fsnotify reloads from what requires caddy reload. - docs/metrics.md aligns the JSON schema with handleMetricsRequest and notes that all counters are process-local. - docs/prometheus.md uses Gauge.set instead of Counter.inc to match the process-local monotonic counter semantics. - caddyfile.example no longer references inexistent directives (country_block, custom_response block form). Also adds the missing CHANGELOG entry for v0.3.0 (duplicate response headers fix and CIDR support in IP blacklist) and removes emoji from all user-facing documentation.
5.3 KiB
5.3 KiB
caddytest.py — Traffic Generator
caddytest.py is a configurable HTTP traffic generator. It mixes legitimate and malicious payloads against a target URL to exercise WAF rules and to stress-test request handling. The script is intended for local benchmarking and rule validation, not as part of an automated CI suite — for the latter use test.py (see testing.md).
Capabilities
- A library of attack payloads covering SQLi, XSS, command injection, LFI, RCE, CRLF injection, SSRF, XXE, XPath, NoSQL, HTTP smuggling, Shellshock, LDAP, and RFI.
- "Composite" requests that mix legitimate and malicious parameters in the same call.
- Configurable behaviour profiles (constant, burst-then-calm, stealth) that change the request mix and pacing over the run.
- Random HTTP method, random path segment, and random cookie generation.
- Concurrency via a configurable thread count, retries, and timeouts.
- Latency metrics (mean, stdev, min/max, median, p95, p99), response-size metrics, status-code distribution, and throughput.
- Optional JSON summary file for machine consumption.
Installation
pip install requests tqdm
Invocation
python3 caddytest.py [OPTIONS]
Options
| Option | Default | Description |
|---|---|---|
--url |
http://localhost:8080 |
Target base URL. |
--method |
GET |
Default HTTP method (GET, POST, PUT, DELETE, OPTIONS). |
--num-requests |
100 |
Total number of requests to send. |
--delay |
1.0 |
Base delay between requests (seconds). |
--delay-jitter |
0.0 |
Maximum jitter added to / subtracted from --delay. |
--attack-type |
all |
Attack key to use (or all for the full set). |
--legit-percent |
0.0 |
Percentage of requests that should be legitimate. |
--composite |
off | Mix legitimate and malicious parameters per request. |
--max-errors |
3 |
Maximum errors before aborting. |
--timeout |
5.0 |
HTTP timeout per request (seconds). |
--max-retries |
0 |
Retries on failure. |
--retry-delay |
0.1 |
Delay between retries (seconds). |
--seed |
none | Random seed for reproducibility. |
--proxy |
none | Outbound proxy URL. |
--threads |
1 |
Concurrent worker threads. |
--random-method |
off | Randomise the HTTP method per request. |
--random-cookies |
off | Add random cookie headers. |
--random-path |
off | Append a random path segment to --url. |
--json |
off | Send payloads as JSON instead of form-encoded. |
--log-file |
none | File for log output. |
--progress |
off | Display a tqdm progress bar. |
--score |
off | Compute a pass / fail score against the expected status codes below. |
--expected-status-legit |
200 |
Expected status code for legitimate requests. |
--expected-status-malicious |
403 |
Expected status code for malicious requests. |
--expected-status-composite |
200 |
Expected status code for composite requests. |
--behavior |
default |
One of default, burst_calm, stealth. |
--insecure |
off | Disable TLS verification. |
--json-summary-file |
none | Path to write a JSON summary at the end. |
Behaviour profiles
| Profile | What it does |
|---|---|
default |
Uses the supplied options unchanged. |
burst_calm |
First 30% of the run: rapid all-malicious burst with minimal delay. Next 30%: slower pace with the user-configured legitimate percentage and increased delay. Last 40%: forced GET requests against scanning-style endpoints (/admin, /config, /login, …). |
stealth |
Bumps the legitimate percentage, slows pacing, restricts methods to GET / POST. |
Examples
# 1000 default requests
python3 caddytest.py --num-requests 1000
# 1000 mostly-legitimate requests, four threads, no delay, stealth profile
python3 caddytest.py --num-requests 1000 --threads 4 --delay 0 \
--legit-percent 100 --behavior stealth --progress
# 500 composite requests with the burst-then-calm profile
python3 caddytest.py --num-requests 500 --composite --behavior burst_calm --progress
# 200 random-method, random-cookie requests; write JSON summary
python3 caddytest.py --num-requests 200 --random-method --random-cookies \
--json-summary-file summary.json --progress
Output
A representative end-of-run summary:
--- Test Summary ---
Total Requests : 1000
Passed : 574 (57.40% success)
Errors : 0 (0.00% error)
Avg Latency : 0.002 s
Std Latency : 0.001 s
Min / Max Latency : 0.001 s / 0.008 s
Median / P95 / P99 : 0.002 s / 0.003 s / 0.004 s
Throughput : 2070.09 requests/s
Avg / Min / Max Body : 5 / 0 / 12 bytes
Median / P95 / P99 : 0 / 12 / 12 bytes
Status Code Distribution: {403: 614, 200: 386}
Total Duration : 0.48 s
When --json-summary-file is provided, the same data is also written as JSON.
Notes
- The script uses Python's
requestslibrary; for HTTP/2 traffic generation use a different tool (e.g.h2load). - Concurrency is thread-based and, on CPython, bound by the GIL for parsing work. The script is I/O-bound in practice and scales reasonably to a few dozen threads.
- Always run the generator from a host you control against a target you control. The payloads are intentionally malicious.