feralbureau/zerodrop

GitHub: feralbureau/zerodrop

一个基于 Caddy forward_auth 和 Redis 的自托管 Web 应用防火墙,提供多层请求过滤与实时仪表板管理。

Stars: 0 | Forks: 0

![Banner](https://static.pigsec.cn/wp-content/uploads/repos/cas/1e/1eaf6b27cd4e50cd101075ab11b2a4a7c79d4d4146defb818e70df467091fbe0.png) # ZeroDrop ### 你的自托管 Web 应用防火墙。 [![Python Version](https://img.shields.io/badge/python-3.11+-3776AB?style=for-the-badge&logo=python&logoColor=white)](https://python.org/) [![License](https://img.shields.io/github/license/feralbureau/zerodrop?style=for-the-badge&color=yellow)](LICENSE) [![Stars](https://img.shields.io/github/stars/feralbureau/zerodrop?style=for-the-badge&color=blue)](https://github.com/feralbureau/zerodrop/stargazers) [![Repo Size](https://img.shields.io/github/repo-size/feralbureau/zerodrop?style=for-the-badge&color=brightgreen)](https://github.com/feralbureau/zerodrop)
## 什么是 ZeroDrop? **ZeroDrop** 是一个自托管的 Web 应用防火墙(WAF),它位于你的应用程序前面并实时过滤恶意流量。它使用 Caddy 的 `forward_auth` 机制拦截每个传入的请求,将其通过多层安全 pipeline 进行处理,然后决定放行还是静默丢弃。 ZeroDrop 不再需要手动配置复杂的防火墙规则,而是为你提供了一个简洁的仪表板来管理黑名单、白名单、拒绝列表、速率限制和正常运行时间监控——所有这些都由 Redis 提供支持,以实现亚毫秒级的决策速度。 ## 核心功能 - **多层请求过滤**:黑名单检查、白名单旁路、蜜罐陷阱、机器人检测、SQLi/XSS 模式匹配,以及 header/query/body 检查——全部集中在单一的 pipeline 中。 - **自适应速率限制**:基于 EWMA 的限流机制,学习每个 IP 的流量模式,并具备应对突发流量的尖峰检测功能。 - **实时仪表板**:React SPA,通过 WebSocket 实时推送拦截事件和正常运行时间状态。 - **正常运行时间监控**:内置 HTTP 和 TCP 健康检查(每 30 秒一次),包含延迟历史记录和实时广播。 - **异常检测**:基于域名的每分钟请求数(RPM)跟踪与尖峰检测(滚动 5 分钟基线,3 倍阈值)。 - **动态反向代理**:自动生成并热重载 Caddy 配置——无需重启即可添加或删除受保护的域名。 - **国家与 User-Agent 拦截**:通过简单的拒绝列表管理,按 Geo-IP 国家代码或 User-Agent 字符串拒绝流量。 - **一键引导**:引导式设置流程,自动生成你的 API key,配置你的第一个域名,并应用 Caddy 配置。 ## 技术栈
![Python](https://img.shields.io/badge/python-%233776AB.svg?style=for-the-badge&logo=python&logoColor=white) ![FastAPI](https://img.shields.io/badge/FastAPI-%23009688.svg?style=for-the-badge&logo=fastapi&logoColor=white) ![Redis](https://img.shields.io/badge/Redis-%23DC382D.svg?style=for-the-badge&logo=redis&logoColor=white) ![Caddy](https://img.shields.io/badge/Caddy-%2322B573.svg?style=for-the-badge&logo=caddy&logoColor=white) ![React](https://img.shields.io/badge/React-%2361DAFB.svg?style=for-the-badge&logo=react&logoColor=black) ![TypeScript](https://img.shields.io/badge/TypeScript-%233178C6.svg?style=for-the-badge&logo=typescript&logoColor=white) ![Tailwind CSS](https://img.shields.io/badge/Tailwind-%2306B6D4.svg?style=for-the-badge&logo=tailwindcss&logoColor=white) ![Docker](https://img.shields.io/badge/Docker-%230db7ed.svg?style=for-the-badge&logo=docker&logoColor=white)
## 安装说明 ### 前置条件 - [Docker](https://www.docker.com/get-started) 和 Docker Compose - Git ### 环境设置 在根目录下创建一个 `.env` 文件: ``` # 提供 dashboard 的 hostname # 如果未提供,则使用 localhost DASHBOARD_HOST=localhost REDIS_URL=redis://localhost:6379/0 ``` ### 使用 Docker 运行 ``` # Clone repository git clone https://github.com/feralbureau/zerodrop.git cd zerodrop # 设置你的 dashboard host echo "DASHBOARD_HOST=localhost" > .env # 启动所有服务 docker compose up --build ``` 打开 `http://localhost` 以访问仪表板。引导流程将指导你完成初始设置。 ### 本地运行(开发模式) ``` # 启动 Redis redis-server # 运行 API server uvicorn app.main:app --reload # 运行 caddy caddy run --config caddy/Caddyfile # 构建 dashboard cd dashboard npm install npm run build # 构建完成后,创建 srv/ 并复制由 Caddy 提供服务的 dashboard bundle mkdir -p ../srv cp -r dist/* ../srv/ ``` 仪表板服务器将可通过 `dash.localhost`(或你配置的主机)访问。 ## 架构 ZeroDrop 由 Docker Compose 编排的三个容器化服务组成。Caddy 是所有流量的单一入口——它提供仪表板服务,并通过 `forward_auth` 对配置的域名强制执行 WAF 保护。 ``` graph TD Client["Client"] --> Caddy["Caddy :80/:443"] Caddy -->|"Dashboard routes"| API["FastAPI :8000"] Caddy -->|"forward_auth /api/check"| API Caddy -->|"If allowed"| Origin["Protected Origin"] API --> Redis["Redis :6379"] API -->|"POST /load"| Caddy ``` ### 请求流程 当请求到达受保护的域名时,Caddy 会先将其转发到 `/api/check`,然后再代理至源站: ``` sequenceDiagram participant Client participant Caddy participant WAF as "/api/check" participant Redis participant Origin as "Protected Origin" Client->>Caddy: "GET https://app.example.com/page" Caddy->>WAF: "Forward auth (X-Real-IP, X-Original-URI)" WAF->>Redis: "Blacklist / Allowlist / Rate checks" alt "Allowed" WAF-->>Caddy: "200 OK" Caddy->>Origin: "Proxy request" Origin-->>Client: "Response" else "Blocked" WAF-->>Caddy: "403 Forbidden (empty body)" Caddy-->>Client: "Connection aborted" end ``` ### WAF Pipeline 每个请求都会按顺序在 `check_ip()` 中通过以下验证层: 1. **白名单** — 如果 IP 或 User-Agent 被列入白名单,则绕过所有检查 2. **拒绝列表** — 按 User-Agent 字符串或国家代码拦截 3. **黑名单** — 如果 IP 已被封禁则立即拒绝 4. **蜜罐** — 对敏感路径(`.env`、`/wp-admin`、`/.git` 等)实施永久封禁 5. **机器人检测** — 拦截已知的机器人 User-Agent 模式(curl、wget、scrapy 等) 6. **Header 检查** — 扫描自定义 header 中的 SQLi/XSS payload 7. **Query 检查** — 扫描 URL 参数中的恶意模式 8. **Body 检查** — 解析 JSON 或原始 body 以查找注入尝试 9. **速率限制** — 基于 EWMA 的自适应限流,具备尖峰检测功能 所有决策都会记录到 Redis stream 中,并实时广播给已连接的仪表板客户端。 ## WAF 规则与开关 每个安全层都可以在仪表板中独立启用或禁用: | 规则 | Key | 默认值 | 描述 | |------|-----|---------|-------------| | 白名单 | `allowlist_enabled` | 开启 | 绕过对受信任 IP/UA 的检查 | | 蜜罐 | `honeypot_enabled` | 开启 | 对访问敏感路径的行为实施永久封禁 | | 机器人 UA | `bot_ua_enabled` | 开启 | 拦截已知的机器人 User-Agent | | Header 检查 | `header_inspection_enabled` | 开启 | 扫描 header 中的 SQLi/XSS | | Query 检查 | `query_inspection_enabled` | 开启 | 扫描 URL 参数中的 payload | | Body 检查 | `body_inspection_enabled` | 开启 | 扫描请求 body 中的注入攻击 | | 速率限制 | `rate_limit_enabled` | 开启 | 固定窗口速率限制(60秒内 100 次请求) | | 自适应速率限制 | `adaptive_rate_limit_enabled` | 开启 | 基于 EWMA 的动态阈值 | | 尖峰检测 | `spike_rate_limit_enabled` | 开启 | 突发流量达到 3 倍时立即拦截 | ## API Endpoints ### REST | Method | Endpoint | Auth | 描述 | |--------|----------|------|-------------| | `POST` | `/api/setup` | 无 | 初始系统设置(API key、域名、配置) | | `GET/POST` | `/api/check` | API Key | WAF 执行 endpoint(由 Caddy 调用) | | `GET` | `/api/key/validate` | 无 | 检查系统是否已配置 | | `POST` | `/api/key/regenerate` | API Key | 生成新的 API key | | `GET/PUT` | `/api/settings` | API Key | 读取/更新 WAF 设置和配置 | | `GET/POST/DELETE` | `/api/domains` | API Key | 管理受保护的域名 | | `GET` | `/api/logs` | API Key | 获取 WAF 事件日志 | | `GET` | `/api/rpm` | API Key | 某个域名的 RPM 时间序列 | | `GET` | `/api/anomalies` | API Key | 某个域名的 RPM 异常事件 | | `GET/POST` | `/api/blacklist` | API Key | 列出/添加黑名单 IP | | `POST` | `/api/unban` | API Key | 从黑名单中移除 IP | | `GET/POST` | `/api/allowlist` | API Key | 列出/添加白名单条目 | | `GET/POST` | `/api/denylist` | API Key | 列出/添加拒绝列表条目 | | `GET/POST/DELETE` | `/api/uptime` | API Key | 管理正常运行时间监控 | | `POST` | `/api/reset` | API Key | 清除所有数据并重新启动引导 | ### WebSocket | Endpoint | 描述 | |----------|-------------| | `/api/ws/logs` | 拦截事件的实时流 | | `/api/ws/uptime` | 实时的正常运行时间监控更新 | | `/api/ws/ping` | 连接检查(响应 `pong`) | ## 仪表板页面 | 页面 | Path | 描述 | |------|------|-------------| | 仪表板 | `/` | 图表和实时安全信息流 | | 黑名单 | `/blacklist` | 被封禁的 IP 和解封操作 | | 白名单 | `/allowlist` | 受信任的来源和绕过规则 | | 域名 | `/domains` | 受保护的站点和源站 | | 设置 | `/settings` | WAF 规则和执行开关 | ## 认证 ZeroDrop 使用存储在 Redis(`waf:api_key`)中的 **API key** 进行认证。所有受保护的 endpoint 都需要通过以下方式提供 key: - `X-API-Key` header,或 - `api_key` query 参数 WebSocket 连接也以相同方式进行身份验证。API key 在引导过程中生成,并可以随时从仪表板中重新生成。 ## Redis Schema | Key 模式 | 类型 | 用途 | |-------------|------|---------| | `waf:api_key` | String | 系统 API key | | `waf:settings` | Hash | WAF 规则开关 | | `waf:domains` | Hash | 域名 → 源站映射 | | `profile:default` | String (JSON) | 用户昵称和头像 | | `blacklist:{ip}` | String | 被拦截的 IP(可选 TTL) | | `rate:{ip}` | String (counter) | 每个时间窗口的请求计数(60秒 TTL) | | `ewma:{ip}` | String (float) | 自适应速率阈值(24小时 TTL) | | `allow:ip`, `allow:ua` | Set | 白名单条目 | | `deny:ua`, `deny:country` | Set | 拒绝列表条目 | | `waf_logs` | Stream | 有序事件日志 | | `uptime:monitors` | Set | 监控 ID | | `uptime:monitor:{id}` | Hash | 监控配置和历史记录 | | `rpm:count:{domain}:{minute}` | String | 原始的每分钟计数器(TTL) | | `rpm:series:{domain}` | ZSet | RPM 序列(24小时) | | `rpm:anomalies:{domain}` | ZSet | RPM 异常事件(24小时) | | `rpm:first_seen:{domain}` | String | 首次记录到流量的时间戳 | ## 许可证 基于 MIT 许可证分发。查看 `LICENSE` 了解更多信息。
标签:AppImage, Caddy, CISA项目, Python, WAF, Web应用防火墙, 搜索引擎查询, 无后门, 流量过滤, 自动化攻击, 请求拦截, 逆向工具, 限流