⚠️ Status: untested. This extension is provided as-is and has not been tested in production. Please feel free to fork, modify, improve, and open pull requests.Licensed under GNU GPLv3 (see LICENSE).
A Caddy v2 HTTP middleware (http.handlers.ip_block) that consults the
ip-block.com decision API and blocks matching client
IPs, with an in-memory per-IP decision cache.
- Tested against: Caddy v2.11.4 (latest stable, June 2026).
- Module ID:
http.handlers.ip_block - Caddyfile directive:
ip_block
| File | Purpose |
|---|---|
ipblock.go |
The middleware (caddyhttp.MiddlewareHandler) + Caddyfile unmarshaler. |
go.mod |
Module definition. |
Caddyfile.example |
Example configuration. |
Caddy plugins are compiled into a custom Caddy binary with
xcaddy:
# From a checkout of this folder (module github.com/ip-block/caddy-ipblock):
xcaddy build v2.11.4 --with github.com/ip-block/caddy-ipblock=.
# Or, once published to a repo:
xcaddy build v2.11.4 --with github.com/ip-block/caddy-ipblockThis produces a caddy binary with the ip_block directive available. Run it
with your Caddyfile: ./caddy run --config Caddyfile.
See Caddyfile.example. Because ip_block is not in Caddy's default directive
order, use it inside a route {} block (or add order ip_block before respond to
the global options).
route {
ip_block {
site_id your-site-id
api_key your-api-key
# ...
}
reverse_proxy localhost:8080
}| Directive | Default | Meaning |
|---|---|---|
enabled |
true |
Master switch. |
site_id |
— (required) | Site id. |
api_key |
— (required) | API key (sent in JSON body). |
api_url |
https://api.ip-block.com/v1/check |
Endpoint. |
fail_open |
true |
Allow on error/timeout; false fails closed. |
cache_ttl |
300 |
Per-IP cache seconds (0 disables). |
timeout_ms |
1000 |
API timeout. |
behind_proxy |
false |
Read client IP from real_ip_header. |
real_ip_header |
X-Forwarded-For |
Header used when behind_proxy. |
block_action |
403 |
403 or redirect. |
block_redirect_url |
https://www.ip-block.com/blocked.php |
Redirect target. |
block_message |
Access denied. |
403 body. |
whitelist |
— | Space-separated IPs never checked. |
You can also configure the handler via native JSON config (the struct's json
tags mirror the directive names).
- Blocks only on
{"action":"block"}; anything else allows (subject tofail_open). - API errors are not cached, so an outage does not pin an IP; the next request
retries.
allow/blockdecisions are cached forcache_ttl. - Whitelisted IPs short-circuit before the cache and API call.
- The 1s timeout is enforced both on the
http.Clientand via a request context deadline.
- The cache is per Caddy process (in-memory
mapguarded by async.RWMutex). - When behind a proxy, prefer Caddy's
trusted_proxiesso the connection IP is already correct;behind_proxy/real_ip_headerare a header-based fallback.