Lightweight Traefik middleware to block sensitive file exposure (.env, .git, backups), neutralize path-evasion tricks, whitelist trusted IPs, and respond cleanly before requests hit your backend.
Live Playground: Test rules, response modes, and bypass behaviors directly in your browser: https://routewarden.github.io/docs/?playground=open
Documentation & Guides: https://routewarden.github.io/docs/
Example Scenarios:examples/(Docker Compose and Kubernetes CRDs)
| Traefik Version | Status | Notes |
|---|---|---|
| Traefik v3.x (v3.0, v3.1, v3.2+) | Supported | Runs via standard Yaegi runtime, Docker labels, and Kubernetes CRDs |
| Traefik v2.x (v2.8 – v2.11+) | Supported | Compatible with Traefik v2 plugin mechanism |
| Traefik v1.x | Not Supported | Traefik v1 does not support plugins |
Web apps accidentally expose sensitive files and administration paths all the time. Automated bots and scanners crawl the internet looking for these files around the clock.
RouteWarden sits directly inside Traefik to catch these requests before they ever reach your upstream application. Written in pure Go with zero external dependencies, it adds minimal overhead while giving you fine-grained control over how scanner probes are handled.
.env*, .git, .aws, .sql, .bak, .conf, .yaml, server logs, and debug endpoints out of the box.%252e%252e), path traversal, matrix parameters (/;param/.env), Windows backslashes, and null bytes before evaluating rules.10.0.0.0/8, 100.64.0.0/10).Instead of manually attaching routewarden to every individual router across dozens of microservices or containers, attaching RouteWarden directly to Traefik's entryPoints (e.g. web on :80 and websecure on :443) enforces security inspection globally for all incoming requests before any router or backend is reached.
All containers routed through Traefik are protected automatically—no router labels required on developer services:
services:traefik:image: traefik:v3.3command:- "--api.insecure=true"- "--providers.docker=true"- "--entrypoints.web.address=:80"# Attach routewarden globally to entryPoint 'web'- "--entrypoints.web.http.middlewares=warden-shield@docker"- "--experimental.plugins.routewarden.modulename=github.com/routewarden/traefik-warden"- "--experimental.plugins.routewarden.version=v1.2.1"ports:- "80:80"volumes:- "/var/run/docker.sock:/var/run/docker.sock:ro"labels:- "traefik.enable=true"# Global EntryPoint middleware definition- "traefik.http.middlewares.warden-shield.plugin.routewarden.enabled=true"- "traefik.http.middlewares.warden-shield.plugin.routewarden.enableDefaultPatterns=true"- "traefik.http.middlewares.warden-shield.plugin.routewarden.response.mode=text"- "traefik.http.middlewares.warden-shield.plugin.routewarden.response.statusCode=404"- "traefik.http.middlewares.warden-shield.plugin.routewarden.response.body=404 page not found"# Any upstream service is now shielded automatically:webapp:image: nginx:alpinelabels:- "traefik.enable=true"- "traefik.http.routers.webapp.rule=Host(`localhost`)"- "traefik.http.routers.webapp.entrypoints=web"
traefik.yml)Attach routewarden@file directly to your global entryPoints:
entryPoints:web:address: ":80"http:middlewares:- warden-shield@filewebsecure:address: ":443"http:middlewares:- warden-shield@fileproviders:file:filename: /etc/traefik/dynamic_conf.ymlexperimental:plugins:routewarden:moduleName: github.com/routewarden/traefik-wardenversion: v1.2.1
dynamic_conf.yml)Define the RouteWarden middleware once in your dynamic provider:
http:middlewares:warden-shield:plugin:routewarden:enabled: trueenableDefaultPatterns: true# Block internal or admin endpointspathPatterns:- '(?i)^/admin(/.*)?$'- '(?i)^/api/internal(/.*)?$'# Allow specific public paths or health checksallowPatterns:- '(?i)^/api/internal/health$'- '(?i)^/robots\.txt$'# Whitelist internal office / VPN rangesallowedIps:- "127.0.0.1"- "10.0.0.0/8"# Return 404 for blocked requestsresponse:mode: textstatusCode: 404body: "404 page not found"routers:# Router needs no middleware declaration—it is protected globally by the entryPoint!app-router:rule: "Host(`app.example.com`)"entryPoints:- webservice: app-service
| Option | Type | Default | Description |
|---|---|---|---|
enabled | bool | true | Enables or disables the middleware. |
enableDefaultPatterns | bool | true | Blocks common sensitive files (.env*, .git, .aws, .sql, .bak, .log, configs). |
enableDefaultAllowPatterns | bool | true | Keeps standard crawler and discovery files accessible (/robots.txt, /sitemap.xml, /.well-known/*). |
pathPatterns | []string | [] | Additional custom regular expressions to block. |
allowPatterns | []string | [] | Regular expressions for paths that should always bypass blocking. |
allowedIps | []string | [] | Trusted IPv4/IPv6 addresses or CIDR blocks allowed to bypass path inspection. |
methods | []string | ["GET"] | HTTP request methods to inspect (for example: ["GET", "POST"]). Other methods pass through. |
checkQuery | bool | false | When true, also inspects query parameters against blocked patterns. |
debug | bool | false | When true, enables verbose debug logging to standard output. |
securityLog | bool | true | When true, emits structured JSON security audit logs on block (CrowdSec / SIEM compatible). |
response.mode | string | "text" | Action to take when a request is blocked: "text", "json", "html", "xml", "captcha", "redirect", "proxy", "silentDrop", "gzipBomb", "tarpit", "fakeSuccess", "rateLimitChallenge", or "infiniteStream". |
response.statusCode | int | 403 | HTTP status code returned to the client (such as 404, 403, 401, or 429). |
response.body | string | "" | Custom payload returned in the response body. |
For the complete list of settings (including Captcha keys, custom HTML templates, and header injection), read the Full Configuration Reference.
Note ongzipBomb: Use this mode only on verified honeypot paths or endpoints targeted exclusively by bots (such as/.envor/wp-login.php). Never use it on shared generic routes where normal users or legitimate crawlers might get caught. Always keepenableDefaultAllowPatterns: trueto avoid blocking/robots.txt.
You can use the official rwarden CLI tool to test path rules offline, validate configurations, and automatically generate Traefik dynamic YAML or Docker Compose labels directly from a unified routewarden.json schema:
# Install RouteWarden CLIcurl -fsSL https://routewarden.github.io/cli/install.sh | bash# Or run via Dockerdocker run --rm ghcr.io/routewarden/cli:latest version
# Generate Traefik dynamic YAML middleware definition (dynamic.yml)rwarden generate --target traefik-yaml --config routewarden.json > dynamic.yml# Generate Traefik dynamic TOML middleware definition (dynamic.toml)rwarden generate --target traefik-toml --config routewarden.json > dynamic.toml# Generate Docker Compose labels blockrwarden generate --target traefik-labels --config routewarden.json# Test a suspicious probe path against rules offlinerwarden test --path "/.env"
For complete documentation on the CLI, installation methods, and options, visit the RouteWarden CLI Documentation.
For detailed setup instructions, architecture deep dives, and production examples, check the documentation:
RouteWarden is tested against automated data races and maintains 98.4% statement test coverage:
# Run tests with the Go race detectorgo test -v -race ./...# Generate coverage profilego test -coverprofile=coverage.out ./... && go tool cover -func=coverage.out
This project is licensed under the MIT License.