Rwx-G/Lorica

GitHub: Rwx-G/Lorica

基于 Cloudflare Pingora 引擎的 Rust 反向代理,将 Web 管理控制台、WAF、SLA 监控和负载测试集成为单一二进制文件,让安全防护与流量管理通过浏览器即可完成。

Stars: 1 | Forks: 0

Lorica

Lorica

A modern, secure, dashboard-first reverse proxy built in Rust

License Version Rust Platform Lorica Tests Inherited Tests

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服务器, 仪表盘, 单文件, 反向代理, 可视化界面, 开发运维工具, 开源, 性能监控, 控制平面, 流量管理, 现代化架构, 网关, 网络安全, 网络安全防御, 网络流量审计, 负载均衡, 路由, 通知系统, 隐私保护, 零依赖