✕
开箱即用的 Caddy 反向代理 + CrowdSec WAF 防护方案
一个预编译的 Caddy Docker 镜像,内置以下模块:
| 模块 | 用途 |
|---|---|
| caddy-crowdsec-bouncer (http/appsec/layer4) | 基于 CrowdSec IP 信誉库自动拦截恶意请求 |
| caddy-l4 | TCP/UDP 四层代理 |
| transform-encoder | 自定义日志输出格式 |
配合 docker-compose.yml,可一键拉起 Caddy + CrowdSec 完整防护栈。
. ├── Dockerfile # 多阶段构建:xcaddy 编译 → 精简运行镜像 ├── docker-compose.yml # Caddy + CrowdSec 编排 ├── .env.example # 环境变量模板 ├── config/ │ ├── caddy/ │ │ └── Caddyfile # Caddy 配置(含 bouncer 示例) │ └── crowdsec/ │ └── acquis.yaml # CrowdSec 日志采集配置 ├── LICENSE ├── CONTRIBUTING.md └── README.md
Internet ──▶ Caddy (:80/:443) ──▶ CrowdSec LAPI 查询 │ │ │ IP 干净 ──────────▶ proxy 到上游服务 │ IP 恶意 ──────────▶ 403 Forbidden │ └──▶ 访问日志 ──▶ CrowdSec Agent 分析 ──▶ 更新决策
预构建镜像支持 linux/amd64 和 linux/arm64 双平台:
docker.cnb.cool/hakurei/caddy-crowdsec-bouncer
| 标签 | Caddy 版本 | 说明 |
|---|---|---|
latest / 2 | Caddy 2.x 最新版 | 推荐使用 |
2.11 | Caddy 2.11.x | 当前稳定版 |
注意:由于
caddy-l4模块要求 Caddy >= 2.11,不提供 2.10 及更早版本的镜像。
# 拉取最新版
docker pull docker.cnb.cool/hakurei/caddy-crowdsec-bouncer:latest
# 拉取指定版本
docker pull docker.cnb.cool/hakurei/caddy-crowdsec-bouncer:2.11
# ARM 设备(如树莓派、Apple Silicon)自动拉取 arm64 镜像
docker pull docker.cnb.cool/hakurei/caddy-crowdsec-bouncer:latest
# 1. 复制环境变量
cp .env.example .env
# 2. 按需修改 Caddyfile
vim config/caddy/Caddyfile
# 3. 启动
docker compose up -d
# 4. 注册 bouncer 并获取 API Key
docker compose exec crowdsec cscli bouncers add caddy-bouncer
# 将输出的 key 填入 .env 的 CROWDSEC_BOUNCER_API_KEY
# 5. 重启 caddy 生效
docker compose restart caddy
首次启动说明: CrowdSec 容器首次启动会自动下载
crowdsecurity/caddy、crowdsecurity/http-cve、crowdsecurity/base-http-scenarios等集合,可能需要等待 30 秒左右。
| 变量 | 默认值 | 说明 |
|---|---|---|
CADDY_VERSION | 2 | Caddy 基础镜像版本 |
CROWDSEC_BOUNCER_API_KEY | — | Bouncer API 密钥(必填) |
CROWDSEC_LAPI_URL | http://crowdsec:8080 | CrowdSec LAPI 地址 |
CADDY_HTTP_PORT | 80 | 对外 HTTP 端口 |
CADDY_HTTPS_PORT | 443 | 对外 HTTPS 端口 |
位于 config/caddy/Caddyfile,关键部分:
{ order crowdsec first order appsec after crowdsec crowdsec { api_url {$CROWDSEC_LAPI_URL} api_key {$CROWDSEC_BOUNCER_API_KEY} ticker_interval 15s appsec_url http://crowdsec:7422 # 开启 AppSec 时取消注释 } } example.com { route { crowdsec # 第一层:IP 信誉拦截 appsec # 第二层:AppSec WAF 深度检测 reverse_proxy localhost:8080 } log { output file /var/log/caddy/access.log format json } }
⚠️ 日志格式必须使用
format json。CrowdSec 的caddy-logsparser 只能解析 JSON 格式的日志,使用transform-encoder等自定义格式会导致日志无法被解析,CrowdSec 将无法检测攻击。
完整语法参考:Caddyfile 文档 · bouncer 配置项
config/crowdsec/acquis.yaml 定义了 CrowdSec 要分析哪些日志:
filenames:
- /var/log/caddy/access.log
labels:
type: caddy
数据(决策数据库、Hub 组件)通过 Docker Volume 持久化,不会因容器重建丢失。
AppSec 在请求内容层面检测攻击(SQL 注入、XSS、已知 CVE 漏洞利用等),是 IP 信誉拦截之上的第二层防护。
docker compose exec crowdsec cscli collections install crowdsecurity/appsec-virtual-patching
docker compose exec crowdsec cscli collections install crowdsecurity/appsec-generic-rules
在 config/crowdsec/acquis.yaml 末尾追加:
---
listen_addr: 0.0.0.0:7422
appsec_config: crowdsecurity/appsec-default
name: appsec
source: appsec
labels:
type: appsec
在全局块中添加 appsec_url,在站点中添加 appsec 指令:
{ order crowdsec first order appsec after crowdsec crowdsec { api_url {$CROWDSEC_LAPI_URL} api_key {$CROWDSEC_BOUNCER_API_KEY} appsec_url http://crowdsec:7422 } } example.com { route { crowdsec appsec reverse_proxy localhost:8080 } }
docker compose restart crowdsec docker compose restart caddy
# 正常请求应返回 200
curl http://your-server/
# CVE 利用应返回 403
curl http://your-server/vendor/phpunit/phpunit/src/Util/PHP/eval-stdin.php
# 查看 AppSec 指标
docker compose exec crowdsec cscli metrics show appsec
# 默认版本
docker build -t caddy-crowdsec-bouncer .
# 指定 Caddy 版本
docker build --build-arg CADDY_VERSION=2.9 -t caddy-crowdsec-bouncer .
需要额外模块?在 Dockerfile 的 xcaddy build 中追加 --with 即可。
如果你已经有运行中的 CrowdSec 实例,不需要 compose 里的 CrowdSec 容器:
docker run -d \ -p 80:80 -p 443:443 \ -v ./config/caddy/Caddyfile:/etc/caddy/Caddyfile \ -e CROWDSEC_LAPI_URL=http://your-crowdsec:8080 \ -e CROWDSEC_BOUNCER_API_KEY=<your-key> \ caddy-crowdsec-bouncer
CrowdSec Console 是官方提供的 Web 管理平台,可以集中查看告警、管理黑名单、下发规则到你的实例。
前往 https://app.crowdsec.net/ 注册并登录。
进入 Security Engines → Add Security Engine,Console 会生成一条 enrollment key。
docker compose exec crowdsec cscli console enroll <your-enrollment-key>
回到 Console 页面,在 Security Engines 列表中找到新实例,点击 Accept。
docker compose restart crowdsec
注册完成后你可以在 Console 上:
# 查看当前封禁决策
docker compose exec crowdsec cscli decisions list
# 查看已注册 bouncer
docker compose exec crowdsec cscli bouncers list
# 手动封禁一个 IP(测试用)
docker compose exec crowdsec cscli decisions add -i 1.2.3.4 -d 10m -t ban
# 查看日志
docker compose logs -f caddy
docker compose logs -f crowdsec
欢迎 PR 和 Issue!详见 CONTRIBUTING.md。