A lightweight reverse proxy that scores the intent of incoming HTTP requests to detect and mitigate bot traffic — without relying on Cloudflare or third-party services.
Inspired by Anubis, Thunderhead takes a passive behavioral approach: it watches how clients move through your site and assigns an intent score based on multiple signals. No JS challenges, no CAPTCHAs — just silent observation and graduated responses.
Every request is scored 0–100 based on:
| Signal | Weight |
|---|---|
robots.txt violation |
+30 |
| Sequential path crawling | +25 |
| High request rate (>30 req/60s) | +20 |
| Suspicious/missing headers | +15 |
| Text-heavy page pattern | +10 |
Based on the score, one of three actions is taken:
| Score | Action |
|---|---|
| < 40 | Allow — pass through to upstream |
| ≥ 40 | Tarpit — delay response (default 5s) |
| ≥ 75 | Block — return 403 Forbidden |
All decisions are logged as structured JSON.
go run ./cmd/thunderheadDefaults to listening on :8080 and proxying to http://localhost:3000.
go run ./cmd/thunderhead -config config.jsongo build ./...{
"listen_addr": ":8080",
"upstream_url": "http://localhost:3000",
"thresholds": {
"tarpit": 40,
"block": 75
},
"tarpit": {
"delay": 5000000000
},
"log_file": ""
}
delayis in nanoseconds.5000000000= 5 seconds.
log_file: leave empty to log to stdout, or provide a file path.
thunderhead/ ├── cmd/thunderhead/ # entrypoint ├── internal/ │ ├── analyzer/ # intent scoring engine │ ├── config/ # config loading │ ├── logger/ # structured JSON logging │ └── proxy/ # reverse proxy + action dispatche
- Auto-fetch and parse
robots.txtfrom upstream -
/thunderhead/statusendpoint for live score inspection - IP/UA allowlist support
- JS challenge response (à la Anubis)
- Middleware mode (Express, Next.js)