Rwx-G/Lorica
GitHub: Rwx-G/Lorica
基于 Cloudflare Pingora 引擎的 Rust 反向代理,将 Web 管理控制台、WAF、SLA 监控和负载测试集成为单一二进制文件,让安全防护与流量管理通过浏览器即可完成。
Stars: 1 | Forks: 0
Lorica
A modern, secure, dashboard-first reverse proxy built in Rust
Lorica 是一个生产就绪的反向代理,内置 Web 控制台、WAF、SLA 监控和 HTTP 缓存。单一二进制文件,零外部依赖。安装后打开浏览器,即可通过 UI 管理一切——路由、后端、证书、安全规则和性能指标。
基于 [Cloudflare Pingora](https://github.com/cloudflare/pingora) 构建,该引擎支撑了 Cloudflare 很大一部分的 CDN 流量。
## 主要特性
### :shield: 代理与路由
- HTTP/HTTPS 反向代理,支持基于主机和路径前缀的路由
- 通过 rustls 实现 TLS 终止(无 OpenSSL 依赖)
- 基于 SNI 的证书选择,支持通配符域名(`*.example.com`)
- 路径重写(剥离/添加前缀、带捕获组的正则表达式)、主机别名、HTTP 到 HTTPS 的重定向
- 可配置的代理头、每路由超时设置、WebSocket 透传
- 具备健康感知后端过滤的连接池
### :lock: 安全
- **WAF 引擎** - 18 条受 OWASP CRS 启发的规则(SQLi、XSS、路径遍历、命令注入、协议违规)
- **IP 黑名单** - 自动从 Data-Shield IPv4 黑名单获取(80 万+ 条目,O(1) 查找,每 6 小时更新)
- **速率限制** - 按路由、按客户端 IP,具有可配置的 RPS 和突发容忍度
- **自动封禁** - 反复超出速率限制的 IP 将被自动封禁(可配置的阈值和持续时间)
- **DDoS 防护** - 按路由的最大连接数、全局洪泛率跟踪
- **Slowloris 检测** - 拒绝慢速头发送攻击,具有可配置的阈值
- **安全头** - 预设(严格/中等/无),包括 HSTS、CSP、X-Frame-Options、X-Content-Type-Options
- 每路由的 **IP 允许名单/拒绝名单** 和 **CORS 配置**
### :bar_chart: 监控与可观测性
- **被动 SLA** - 每路由的正常运行时间、延迟百分位数(p50/p95/p99)、滑动窗口(1 小时/24 小时/7 天/30 天)
- **主动 SLA** - 可配置间隔的合成 HTTP 探测,可在低流量期间检测停机
- **Prometheus 指标** - `/metrics` 端点提供请求计数、延迟直方图、后端健康状况、WAF 事件、证书过期信息
- **实时访问日志** - 通过 WebSocket 流式传输到控制台,并支持过滤
- **负载测试** - 内置负载测试引擎,支持 SSE 流式传输、cron 调度、CPU 熔断器和结果比较
- **SLA 违规警报** - 当 SLA 降至目标以下时自动通知
### :globe_with_meridians: 管理
- **Web 控制台** - 嵌入在二进制文件中的 Svelte 5 UI(约 59 KB):路由、后端、证书、WAF、SLA、负载测试、设置
- **REST API** - 对所有实体的完整 CRUD 操作、基于会话的身份验证、限速登录
- **TOML 配置导出/导入** - 应用更改前带有差异预览
- **Nginx 配置导入** - 粘贴 `nginx.conf` 以自动创建路由、后端和证书
- **ACME / Let's Encrypt** - 通过 HTTP-01 挑战自动配置 TLS
- **通知渠道** - stdout、SMTP 电子邮件、HTTP webhook,支持按渠道的速率限制
- **封禁名单管理** - 从控制台查看和解除自动封禁的 IP
### :zap: 性能
- **Pingora 引擎** - 从 Cloudflare 的生产代理框架分叉而来
- **HTTP 缓存** - 内存中的响应缓存,采用 LRU 驱逐(128 MiB 上限),TinyUFO 算法
- **峰值 EWMA 负载均衡** - 感知延迟的后端选择,同时支持 Round Robin、Consistent Hash、Random
- **DashMap** - 在热路径中对封禁名单和路由连接进行无锁并发读取
- **亚 0.5 毫秒的 WAF 评估** - 预编译的正则表达式模式,禁用时零开销
### :package: 可靠性
- **Worker 进程隔离** - 通过 SCM_RIGHTS 传递套接字的 fork+exec
- **Protobuf 命令通道** - Supervisor 到 Worker 的配置重载,不中断流量
- **健康检查** - TCP 和 HTTP 探测,后端标记为降级(>2 秒)或宕机并从轮换中移除
- **优雅排空** - 针对后端的活跃连接跟踪,具有 Closing/Closed 生命周期状态
- **证书热替换** - 通过 arc-swap 进行原子交换,轮换期间零停机
- **加密存储** - 对静态的证书私钥进行 AES-256-GCM 加密
## 快速开始
### 通过 .deb 包安装
```
# 下载最新版本
wget https://github.com/Rwx-G/Lorica/releases/latest/download/lorica.deb
sudo dpkg -i lorica.deb
sudo systemctl enable --now lorica
```
### 直接运行
```
lorica --data-dir /var/lib/lorica
```
在浏览器中打开 `https://localhost:9443`。首次运行时,随机的管理员密码将打印到标准输出。
### CLI 选项
```
lorica [OPTIONS]
Options:
--data-dir
Data directory (default: /var/lib/lorica)
--management-port Dashboard/API port (default: 9443)
--http-port HTTP proxy port (default: 80)
--https-port HTTPS proxy port (default: 443)
--workers Worker processes (default: 0 = single-process)
--log-level Log level (default: info)
--version Print version
```
## 控制台
控制台内置于二进制文件中,并在管理端口(默认 9443)上提供服务。它提供:
- **总览** - 仪表盘,包含路由/后端/证书/警报摘要卡、SLA 图表、请求率迷你图、热门路由表和最近的事件时间线
- **路由** - 创建/编辑路由,支持主机匹配、路径前缀、负载均衡、WAF 模式、速率限制、缓存、超时、安全头、CORS,以及可折叠“高级配置”部分中的另外 25 项每路由设置
- **后端** - 管理后端地址、权重、健康检查类型(TCP/HTTP)、TLS 上游、活跃连接、生命周期状态
- **证书** - 上传 PEM 证书,查看过期日期,通过 ACME/Let's Encrypt 进行配置
- **安全** - 带有类别过滤的 WAF 事件表、每个攻击类别的统计信息、规则开关、带解封按钮的封禁名单
- **SLA** - 每路由的被动/主动 SLA 并排展示、延迟百分位表、配置编辑器、CSV/JSON 导出
- **负载测试** - 测试配置管理,支持克隆、一键执行、实时 SSE 进度面板、历史结果
- **活跃探测** - 合成健康探测的 CRUD,支持路由选择、HTTP 方法/路径/状态/间隔/超时
- **访问日志** - 通过 WebSocket 实现带绿色脉冲指示器的可滚动实时日志流
- **设置** - 通知渠道(stdout/SMTP/webhook)、拓扑配置、带有差异预览的配置导出/导入
- **主题** - 亮/暗模式切换
## 架构
Lorica 是一个包含 25 个 crate 的 Rust 工作区:15 个从 Cloudflare Pingora 分叉而来,10 个为产品 crate。有关完整的分叉谱系和重命名规则,请参见 [FORK.md](FORK.md)。
| Crate | 用途 |
|-------|---------|
| `lorica` | CLI 二进制文件、Supervisor、Worker 编排 |
| `lorica-proxy` | HTTP/HTTPS 代理引擎(Pingora 分叉) |
| `lorica-tls` | SNI 证书解析器、热替换、ACME |
| `lorica-config` | SQLite 存储、迁移、TOML 导出/导入 |
| `lorica-api` | axum REST API、身份验证、会话管理 |
| `lorica-dashboard` | 通过 rust-embed 嵌入的 Svelte 5 前端 |
| `lorica-waf` | WAF 引擎、OWASP 规则、IP 黑名单 |
| `lorica-notify` | 警报分发 |
| `lorica-bench` | SLA 监控、负载测试引擎 |
| `lorica-worker` | fork+exec Worker 隔离、套接字传递 |
| `lorica-command` | Protobuf Supervisor-Worker 命令通道 |
| `lorica-lb` | 负载均衡 |
| `lorica-cache` | HTTP 响应缓存、LRU 驱逐 |
| `lorica-limits` | 用于速率限制的速率估算器 |
数据平面(代理)和控制平面(API/控制台)完全分离。API 变更通过 arc-swap 触发配置重载——代理无需重启即可获取更改。
## 性能
在单个 Linux 虚拟机(4 vCPU,8 GB 内存)上测量:
| 指标 | 数值 |
|--------|-------|
| 单进程吞吐量 | ~6,500 请求/秒 |
| 多 Worker 吞吐量(4 个 Worker) | ~25,000 请求/秒 |
| WAF 评估延迟 | 每请求 < 0.5 毫秒 |
| WAF 对吞吐量的开销 | ~6% |
| 控制台打包大小 | ~59 KB (gzipped) |
| 配置重载 | 零停机 |
| 证书热替换 | 零停机 (原子操作) |
## 配置示例
通过 REST API 创建路由:
```
# 认证
TOKEN=$(curl -sk https://localhost:9443/api/v1/auth/login \
-H 'Content-Type: application/json' \
-d '{"password":"your-admin-password"}' \
-c - | grep session | awk '{print $NF}')
# 创建 backend
curl -sk https://localhost:9443/api/v1/backends \
-b "session=$TOKEN" \
-H 'Content-Type: application/json' \
-d '{
"address": "127.0.0.1:8080",
"health_check_interval_s": 10,
"health_check_type": "http",
"health_check_path": "/healthz"
}'
# 创建 route
curl -sk https://localhost:9443/api/v1/routes \
-b "session=$TOKEN" \
-H 'Content-Type: application/json' \
-d '{
"hostname": "app.example.com",
"path_prefix": "/",
"backend_ids": [1],
"load_balancing": "peak_ewma",
"tls_enabled": true,
"certificate_id": 1,
"waf_enabled": true,
"waf_mode": "block",
"rate_limit_rps": 100,
"rate_limit_burst": 50,
"cache_enabled": true,
"cache_ttl_s": 300,
"force_https": true,
"security_headers": "strict"
}'
```
或者直接使用控制台——它涵盖了所有相同的操作,完全不需要 curl。
## REST API 参考
所有端点均通过 HTTPS 在管理端口(默认 `9443`)上提供服务。受保护的端点需要通过 `/api/v1/auth/login` 获取的会话 Cookie。
### 公开端点
| 方法 | 路径 | 描述 |
|--------|------|-------------|
| `POST` | `/api/v1/auth/login` | 身份验证(返回会话 Cookie) |
| `POST` | `/api/v1/auth/logout` | 使会话失效 |
| `GET` | `/metrics` | Prometheus 指标(无需认证) |
| `GET` | `/.well-known/acme-challenge/:token` | ACME HTTP-01 挑战响应 |
### 路由
| 方法 | 路径 | 描述 |
|--------|------|-------------|
| `GET` | `/api/v1/routes` | 列出所有路由 |
| `POST` | `/api/v1/routes` | 创建路由 |
| `GET` | `/api/v1/routes/:id` | 获取路由 |
| `PUT` | `/api/v1/routes/:id` | 更新路由 |
| `DELETE` | `/api/v1/routes/:id` | 删除路由 |
### 后端
| 方法 | 路径 | 描述 |
|--------|------|-------------|
| `GET` | `/api/v1/backends` | 列出所有后端 |
| `POST` | `/api/v1/backends` | 创建后端 |
| `GET` | `/api/v1/backends/:id` | 获取后端 |
| `PUT` | `/api/v1/backends/:id` | 更新后端 |
| `DELETE` | `/api/v1/backends/:id` | 删除后端 |
### 证书
| 方法 | 路径 | 描述 |
|--------|------|-------------|
| `GET` | `/api/v1/certificates` | 列出证书 |
| `POST` | `/api/v1/certificates` | 上传 PEM 证书 |
| `POST` | `/api/v1/certificates/self-signed` | 生成自签名证书 |
| `GET` | `/api/v1/certificates/:id` | 获取证书 |
| `PUT` | `/api/v1/certificates/:id` | 更新证书 |
| `DELETE` | `/api/v1/certificates/:id` | 删除证书 |
### ACME
| 方法 | 路径 | 描述 |
|--------|------|-------------|
| `POST` | `/api/v1/acme/provision` | 通过 HTTP-01 配置 |
| `POST` | `/api/v1/acme/provision-dns` | 通过 DNS-01 配置 |
| `POST` | `/api/v1/acme/provision-dns-manual` | 启动手动 DNS-01 流程 |
| `POST` | `/api/v1/acme/provision-dns-manual/confirm` | 确认手动 DNS-01 |
### WAF
| 方法 | 路径 | 描述 |
|--------|------|-------------|
| `GET` | `/api/v1/waf/events` | 最近的 WAF 事件(带类别过滤器) |
| `DELETE` | `/api/v1/waf/events` | 清除 WAF 事件 |
| `GET` | `/api/v1/waf/stats` | WAF 统计信息 |
| `GET` | `/api/v1/waf/rules` | 列出 WAF 规则 |
| `PUT` | `/api/v1/waf/rules/:id` | 启/禁用规则 |
| `GET` | `/api/v1/waf/rules/custom` | 列出自定义规则 |
| `POST` | `/api/v1/waf/rules/custom` | 创建自定义规则 |
| `DELETE` | `/api/v1/waf/rules/custom/:id` | 删除自定义规则 |
| `GET` | `/api/v1/waf/blocklist` | 黑名单状态 |
| `PUT` | `/api/v1/waf/blocklist` | 启用/禁用黑名单 |
| `POST` | `/api/v1/waf/blocklist/reload` | 重新加载黑名单 |
### SLA 与探测
| 方法 | 路径 | 描述 |
|--------|------|-------------|
| `GET` | `/api/v1/sla/overview` | 所有路由的 SLA 概览 |
| `GET` | `/api/v1/sla/routes/:id` | 路由的 SLA 指标 |
| `GET` | `/api/v1/sla/routes/:id/buckets` | 按时间桶分组的 SLA 数据 |
| `GET` | `/api/v1/sla/routes/:id/config` | SLA 配置 |
| `PUT` | `/api/v1/sla/routes/:id/config` | 更新 SLA 配置 |
| `GET` | `/api/v1/sla/routes/:id/export` | 导出 SLA 数据(CSV/JSON) |
| `GET` | `/api/v1/sla/routes/:id/active` | 主动探测结果 |
| `GET` | `/api/v1/probes` | 列出探测 |
| `POST` | `/api/v1/probes` | 创建探测 |
| `GET` | `/api/v1/probes/route/:route_id` | 路由的探测 |
| `PUT` | `/api/v1/probes/:id` | 更新探测 |
| `DELETE` | `/api/v1/probes/:id` | 删除探测 |
### 负载测试
| 方法 | 路径 | 描述 |
|--------|------|-------------|
| `GET` | `/api/v1/loadtest/configs` | 列出配置 |
| `POST` | `/api/v1/loadtest/configs` | 创建配置 |
| `PUT` | `/api/v1/loadtest/configs/:id` | 更新配置 |
| `DELETE` | `/api/v1/loadtest/configs/:id` | 删除配置 |
| `POST` | `/api/v1/loadtest/configs/:id/clone` | 克隆配置 |
| `POST` | `/api/v1/loadtest/start/:config_id` | 开始测试(需要确认) |
| `POST` | `/api/v1/loadtest/start/:config_id/confirm` | 确认并执行 |
| `GET` | `/api/v1/loadtest/status` | 当前测试状态 |
| `GET` | `/api/v1/loadtest/stream` | SSE 实时结果 |
| `POST` | `/api/v1/loadtest/abort` | 中止正在运行的测试 |
| `GET` | `/api/v1/loadtest/results/:config_id` | 测试结果 |
| `GET` | `/api/v1/loadtest/results/:config_id/compare` | 比较运行结果 |
### 缓存与封禁
| 方法 | 路径 | 描述 |
|--------|------|-------------|
| `DELETE` | `/api/v1/cache/routes/:id` | 清除路由缓存 |
| `GET` | `/api/v1/cache/stats` | 缓存命中/未命中统计 |
| `GET` | `/api/v1/bans` | 列出被封禁的 IP |
| `DELETE` | `/api/v1/bans/:ip` | 解封 IP |
### 系统与配置
| 方法 | 路径 | 描述 |
|--------|------|-------------|
| `PUT` | `/api/v1/auth/password` | 更改密码 |
| `GET` | `/api/v1/settings` | 全局设置 |
| `PUT` | `/api/v1/settings` | 更新设置 |
| `GET` | `/api/v1/status` | 系统状态摘要 |
| `GET` | `/api/v1/system` | CPU、内存、磁盘使用情况 |
| `GET` | `/api/v1/workers` | Worker 心跳指标 |
| `GET` | `/api/v1/logs` | 访问日志 |
| `DELETE` | `/api/v1/logs` | 清除日志 |
| `GET` | `/api/v1/logs/ws` | WebSocket 日志流 |
| `POST` | `/api/v1/config/export` | 以 TOML 导出配置 |
| `POST` | `/api/v1/config/import` | 导入 TOML 配置 |
| `POST` | `/api/v1/config/import/preview` | 预览导入差异 |
| `GET` | `/api/v1/notifications` | 列出通知配置 |
| `POST` | `/api/v1/notifications` | 创建通知配置 |
| `PUT` | `/api/v1/notifications/:id` | 更新通知配置 |
| `DELETE` | `/api/v1/notifications/:id` | 删除通知配置 |
| `POST` | `/api/v1/notifications/:id/test` | 测试通知渠道 |
| `GET` | `/api/v1/preferences` | 列出用户偏好设置 |
| `PUT` | `/api/v1/preferences/:id` | 更新偏好设置 |
| `DELETE` | `/api/v1/preferences/:id` | 删除偏好设置 |
## 从源码构建
```
# 先决条件
# - Rust 1.88+
# - Node.js 18+ (用于 dashboard 编译)
# - Linux (x86_64)
git clone https://github.com/Rwx-G/Lorica.git
cd Lorica
cargo build --release
# Binary 位于 target/release/lorica
# Svelte frontend 会在 cargo build 期间自动编译。
```
### 运行测试
```
# 所有 Rust 单元测试 (跨 25 个 crate 共 655 个测试)
cargo test
# 仅 Product crate 测试 (280 个测试)
cargo test -p lorica-config -p lorica-waf -p lorica-api -p lorica-notify -p lorica-bench
# Frontend 测试 (52 个 Vitest 测试)
cd lorica-dashboard/frontend && npx vitest run
# E2E 测试 (跨 35 个 section 超过 170 个断言,需要 Docker)
cd tests-e2e-docker && ./run.sh --build
```
## systemd 服务
`.deb` 和 `.rpm` 包安装了一个经过安全强化的 systemd 单元,具有以下特性:
- `ProtectSystem=strict`、`PrivateTmp=yes`、`NoNewPrivileges=yes`
- `MemoryDenyWriteExecute=yes`、`SystemCallFilter=@system-service`
- `RestrictNamespaces=yes`、`RestrictSUIDSGID=yes`
- 以专用的 `lorica` 用户运行,并赋予 `CAP_NET_BIND_SERVICE` 权限
- 安装时自动启动,升级时自动重启
- 数据目录(`/var/lib/lorica`)在升级时予以保留
通过 drop-in 覆盖自定义服务(例如启用 Worker):
```
sudo systemctl edit lorica
```
```
[Service]
ExecStart=
ExecStart=/usr/bin/lorica --workers 6
```
## 性能调优
有关内核参数(`sysctl`)、文件描述符限制、Worker 配置、缓存设置和生产就绪清单,请参见 [docs/tuning.md](docs/tuning.md)。运行 [bench/](bench/) 以获取可重现的吞吐量测量结果。
## 包验证
发布的 `.deb` 和 `.rpm` 包均经过 GPG 签名。导入公钥以进行验证:
```
curl -fsSL https://github.com/Rwx-G/Lorica/raw/main/docs/lorica-signing-key.asc | sudo gpg --dearmor -o /usr/share/keyrings/lorica.gpg
gpg --verify lorica.deb.asc lorica.deb
```
## 不支持
| 特性 | 状态 | 原因 |
|---------|--------|-----------|
| **HTTP/3 / QUIC** | 已计划(0.2.0 之后) | 等待 [Pingora PR #524](https://github.com/cloudflare/pingora/pull/524)(tokio-quiche 集成)合并到上游 |
| **io_uring** | 不计划支持 | tokio-uring 自 2022 年起已无人维护。通过 Tokio 的 epoll 提供了充足的性能(在 Cloudflare 规模下可达 4000 万请求/秒) |
| **Windows / macOS** | 不支持 | 仅限 Linux x86_64(fork+exec Worker 模型需要 Linux) |
| **OpenSSL / BoringSSL** | 已移除 | rustls 是唯一的 TLS 提供者 |
## 许可证
Apache-2.0 - 详见 [LICENSE](LICENSE)。
## 致谢
基于 Cloudflare 的 [Pingora](https://github.com/cloudflare/pingora)(Apache-2.0)构建。有关分叉的详细信息,请参见 [NOTICE](NOTICE) 和 [FORK.md](FORK.md)。
作者:Rwx-G标签:AppImage, CDN, CISA项目, Cloudflare, HTTP缓存, IP黑名单, MITRE ATT&CK, Pingora, Rust, SLA监控, TLS卸载, WAF, Web应用防火墙, Web服务器, 仪表盘, 单文件, 反向代理, 可视化界面, 开发运维工具, 开源, 性能监控, 控制平面, 流量管理, 现代化架构, 网关, 网络安全, 网络安全防御, 网络流量审计, 负载均衡, 路由, 通知系统, 隐私保护, 零依赖