mirror of
https://github.com/Rain-kl/OpenFlare.git
synced 2026-10-01 22:46:38 +08:00
[新增] OpenFlare Pages
This commit is contained in:
@@ -98,10 +98,11 @@ Agent 对数据面 OpenResty 的管控实现了端到端的闭环,包含配置
|
||||
* `certs/`:证书存放目录(文件命名为 `{cert_id}.crt` 和 `{cert_id}.key`)。
|
||||
* `waf/` 与 `pow/`:WAF 及防 CC 挑战所需的专用 Lua 运行时脚本。
|
||||
* `waf_config.json` 与 `waf_ip_groups.json`:WAF 过滤引擎所需的结构化规则配置文件。
|
||||
* `pages_dir`:Pages 静态站点部署目录,默认位于 `data_dir/var/lib/openflare/pages`。当激活配置引用 Pages 部署时,Agent 会下载部署 zip、校验 checksum、解压到部署 release 目录,并切换 `deployments/{deployment_id}/current` 供 OpenResty `root`/`try_files` 读取。
|
||||
|
||||
### 2. 精细化的重载动作
|
||||
1. **备份当前配置**:在写入新文件之前,Agent 会将现有的配置文件复制到 `.backup` 临时目录下,保留完整的现场快照。
|
||||
2. **写入并替换占位符**:将最新拉取的模板写入,自动将模板中的绝对路径占位符(如 `__OPENFLARE_LUA_DIR__`)替换为本地实际运行路径。
|
||||
2. **写入并替换占位符**:将最新拉取的模板写入,自动将模板中的绝对路径占位符(如 `__OPENFLARE_LUA_DIR__`、`__OPENFLARE_PAGES_DIR__`)替换为本地实际运行路径。
|
||||
3. **语法校验**:调用 `openresty -t -c <temp_nginx.conf>` 进行严格的语法测试。
|
||||
4. **平滑重载**:若校验通过,将新配置移至正式路径,执行 `openresty -s reload`。若 OpenResty 处于未启动状态,则使用当前配置拉起进程。
|
||||
5. **捕获异常**:校验或重载失败时,Agent 会截获标准错误输出(stderr),提取前 2000 个字符的详细报错信息。
|
||||
@@ -117,7 +118,7 @@ OpenFlare 摒弃了动态 Patch 节点配置的落后方式,采用 **不可变
|
||||
```
|
||||
|
||||
### 1. 核心设计原则
|
||||
* **完整发布**:每次发布均是对当前控制面所有启用路由、证书、全局与局部 WAF 规则进行一次性全量编译,生成带唯一 `checksum` 的完整版本。
|
||||
* **完整发布**:每次发布均是对当前控制面所有启用路由、证书、Pages 部署引用、全局与局部 WAF 规则进行一次性全量编译,生成带唯一 `checksum` 的完整版本。
|
||||
* **版本格式**:采用 `YYYYMMDD-NNN` 递增格式,确保版本历史直观、具备单调递增性。
|
||||
* **全局单激活版本**:系统同时只有一个处于 `active` 状态的全局配置版本。回滚时无需逆向打补丁,只需将历史某个健康版本的状态改为 `active`,Agent 重新拉取应用即可。
|
||||
|
||||
@@ -171,4 +172,4 @@ graph TD
|
||||
|
||||
1. **零特权指令通道**:Server 绝对禁止向 Agent 传递任何任意 shell 命令或远程执行脚本(如 exec/eval 等)。所有系统控制原语(如启动、停止、重载、更新)必须硬编码在 Agent 二进制内部。
|
||||
2. **严格的 Token 过滤与前缀验证**:Agent 侧向 Server 请求资源时,接口端点固定以 `/api/agent/` 为前缀,并强制携带 `X-Agent-Token` 进行签名或令牌核验。
|
||||
3. **节点自治原则**:Agent 须具备完备的离线工作能力。在与 Server 失去连接期间,本地 OpenResty 必须依靠本地已落地的配置保持反向代理服务的绝对正常运行。
|
||||
3. **节点自治原则**:Agent 须具备完备的离线工作能力。在与 Server 失去连接期间,本地 OpenResty 必须依靠本地已落地的配置保持反向代理服务的绝对正常运行。
|
||||
|
||||
@@ -48,13 +48,27 @@ OpenFlared (frpc) <-- 内网服务器
|
||||
Internal Service (192.168.x.x)
|
||||
```
|
||||
|
||||
### Pages 静态托管流量路径
|
||||
|
||||
```text
|
||||
Browser
|
||||
|
|
||||
| HTTPS request
|
||||
v
|
||||
OpenResty (Agent, TLS/WAF)
|
||||
|
|
||||
| root/try_files
|
||||
v
|
||||
Agent 本地 Pages 部署目录
|
||||
```
|
||||
|
||||
## 组件职责
|
||||
|
||||
| 组件 | 职责 |
|
||||
| --------------- | ---------------------------------------------------------------------- |
|
||||
| Server | 管理端 UI、管理 API、Agent/Relay/Client API、配置渲染、版本发布、数据存储与聚合查询 |
|
||||
| Agent | 注册、心跳、同步、写入文件、校验、reload、失败回滚、自更新与轻量采集 |
|
||||
| OpenResty | 接收真实流量,按 OpenFlare 渲染的配置执行 WAF、PoW、认证与反向代理 |
|
||||
| Server | 管理端 UI、管理 API、Agent/Relay/Client API、配置渲染、版本发布、Pages 部署包存储、数据存储与聚合查询 |
|
||||
| Agent | 注册、心跳、同步、写入文件、Pages 部署包拉取与解压、校验、reload、失败回滚、自更新与轻量采集 |
|
||||
| OpenResty | 接收真实流量,按 OpenFlare 渲染的配置执行 WAF、PoW、认证、反向代理与 Pages 静态文件服务 |
|
||||
| OpenFlareRelay | 管理 frps 进程生命周期,提供隧道中继服务,通过心跳接收 frps 配置 |
|
||||
| OpenFlared | 管理 frpc 进程(可多个),连接 Relay 中继,将流量转发到内网服务 |
|
||||
| Frontend | 管理网站配置、WAF、源站、证书、节点、Tunnel、版本、用户、设置与观测页面 |
|
||||
@@ -71,6 +85,8 @@ Internal Service (192.168.x.x)
|
||||
|
||||
Server 不直接 SSH 到节点,也不在线修改节点文件。它只保存控制面状态、生成完整配置版本,并通过 Agent API 让节点主动拉取。
|
||||
|
||||
Pages 静态托管场景中,Server 保存 Pages 项目、不可变部署元数据、文件清单和 zip 部署包;发布版本只记录部署引用和 checksum,不把大体积静态资源写入 `config_versions`。
|
||||
|
||||
## Agent
|
||||
|
||||
`openflare_agent` 是 Go 单体程序:
|
||||
@@ -79,6 +95,7 @@ Server 不直接 SSH 到节点,也不在线修改节点文件。它只保存
|
||||
* 启动后读取或生成本地节点信息。
|
||||
* 周期性 heartbeat,上报状态并获取激活版本摘要。
|
||||
* 发现新版本后拉取配置、备份旧文件、写入新文件、校验并 reload。
|
||||
* 当激活配置引用 Pages 部署时,先按部署 ID 下载 zip 包,校验 checksum,解压到本地 `pages_dir` 并切换当前部署目录。
|
||||
* 应用失败时尝试恢复运行并回滚。
|
||||
* 维护 WAF GeoIP mmdb,启动时写入内置初始库,并按配置定期更新。
|
||||
|
||||
@@ -118,6 +135,7 @@ Browser -> Frontend -> /api/* -> controller -> service -> model -> database
|
||||
```text
|
||||
Agent HTTP heartbeat -> Server 返回激活版本摘要
|
||||
Agent 发现新版本 -> 拉取配置详情
|
||||
Agent 确保 Pages 部署包已下载、校验并解压 (如配置引用 Pages)
|
||||
Agent 写入主配置 / 路由配置 / 证书 / Lua 资源 / WAF 运行时配置
|
||||
Agent 执行 OpenResty 校验与 reload
|
||||
Agent 上报应用结果
|
||||
@@ -180,6 +198,9 @@ WAF IP 组由 Server 管理。手动 IP 组直接保存 IP/IP 段列表;自动
|
||||
* `proxy_routes`
|
||||
* `origins`
|
||||
* `config_versions`
|
||||
* `pages_projects`
|
||||
* `pages_deployments`
|
||||
* `pages_deployment_files`
|
||||
* `nodes`
|
||||
* `tunnels`
|
||||
* `auth_sources`
|
||||
|
||||
+17
-1
@@ -32,6 +32,7 @@ OpenFlare 当前不定位为通用日志平台、服务网格、Kubernetes Ingre
|
||||
| 管理端前端 | 基于 Next.js 的正式管理端 |
|
||||
| 认证源登录 | 支持以认证源形式配置 GitHub 与标准 OIDC 登录入口,并允许第三方账号绑定已有本地用户 |
|
||||
| 内网穿透 | 通过 TunnelRelay 节点与 OpenFlared 客户端,将内网 HTTP 服务安全暴露到公网,复用 Agent 的 HTTPS/WAF 能力 |
|
||||
| Pages 静态托管 | 以 Pages 项目管理静态站点部署包,发布后由边缘 Agent 拉取并在本地 OpenResty 静态服务 |
|
||||
|
||||
默认工作方式:
|
||||
|
||||
@@ -52,6 +53,7 @@ OpenFlare 当前不定位为通用日志平台、服务网格、Kubernetes Ingre
|
||||
| 证书托管 | 为不同域名绑定 TLS 证书 |
|
||||
| 基础观测 | 查看节点状态、请求聚合、访问分析和健康事件 |
|
||||
| 内网穿透 | 通过 Tunnel 将无法直接公网访问的内网 HTTP 服务暴露到互联网,享有 HTTPS、WAF 等全部防护能力 |
|
||||
| 静态站点托管 | 上传已构建的静态资源包,将网站规则上游绑定到 Pages 项目,在边缘节点本地服务静态文件 |
|
||||
|
||||
|
||||
## 网站配置约束
|
||||
@@ -72,12 +74,26 @@ OpenFlare 当前不定位为通用日志平台、服务网格、Kubernetes Ingre
|
||||
|
||||
上游约束:
|
||||
|
||||
* `proxy_routes` 至少包含一个上游地址(直连类型 `direct`),或关联一个 Tunnel(内网穿透类型 `tunnel`)。
|
||||
* `proxy_routes` 至少包含一个上游地址(直连类型 `direct`),或关联一个 Tunnel(内网穿透类型 `tunnel`),或关联一个 Pages 项目(静态托管类型 `pages`)。
|
||||
* 多上游负载均衡统一渲染为带 keepalive 的 named `upstream`。
|
||||
* 单上游允许附带 base path 或 query,并在 `proxy_pass` 中追加。多上游限定为纯 `scheme://host[:port]` 结构,且同一规则内的协议必须一致。
|
||||
* `proxy_routes.origin_host` 为可选字段,用于回源时覆盖 `Host` 请求头。
|
||||
* 所有直连类型上游地址都必须为合法的 `http://` 或 `https://`。
|
||||
* 内网穿透类型上游必须关联有效 `tunnel_id`,并指定内网目标地址与协议。
|
||||
* Pages 类型上游必须关联有效 Pages 项目,且项目必须存在已激活部署。Pages 站点不执行服务端构建、边缘函数或动态运行时代码,仅托管预构建静态资源。
|
||||
|
||||
## Pages 静态托管约束
|
||||
|
||||
OpenFlare Pages 面向边缘节点静态站点托管,采用“项目 + 不可变部署 + 网站规则绑定”的模型。
|
||||
|
||||
约束:
|
||||
|
||||
* Pages 项目保存名称、标识、启用状态、SPA fallback 选项和当前激活部署。
|
||||
* Pages 部署由管理端上传预构建 zip 包生成;部署包保存在 Server 本地 Pages 存储目录,数据库只保存部署元数据和文件清单,不保存大体积文件内容。
|
||||
* 只有项目存在激活部署后,`proxy_routes.upstream_type = 'pages'` 的网站规则才能绑定该项目。
|
||||
* Pages 网站继续复用网站规则的域名、HTTPS、WAF、PoW、Basic Auth、限流、缓存配置和配置版本发布机制。
|
||||
* 发布快照保存 Pages 项目、部署 ID、部署 checksum、入口文件和 SPA fallback 选项。Agent 拉取激活配置时按部署 checksum 下载并校验部署包,解压到本地 `pages_dir` 后再应用 OpenResty 配置。
|
||||
* V1 不支持 Git 自动构建、预览域名、边缘函数、动态 SSR、外部对象存储或多租户隔离。
|
||||
|
||||
## 内网穿透约束
|
||||
|
||||
|
||||
@@ -61,6 +61,7 @@ Frontend:
|
||||
|
||||
### 1. 当前有效实体
|
||||
* **核心配置与反代**:`proxy_routes` (网站配置), `origins` (源站), `config_versions` (配置版本), `tls_certificates` (证书), `managed_domains` (托管域名).
|
||||
* **Pages 静态托管**:`pages_projects` (Pages 项目), `pages_deployments` (不可变部署), `pages_deployment_files` (部署文件清单).
|
||||
* **节点与状态**:`nodes` (节点), `node_system_profiles` (系统概况), `apply_logs` (应用日志).
|
||||
* **内网穿透**:`tunnels` (隧道客户端), `tunnel_tokens` (隧道认证令牌,可选持久化).
|
||||
* **观测与分析**:`node_request_reports` (请求上报), `node_access_logs` (访问明细), `node_metric_snapshots` (指标快照), `traffic_analytics_rollups` (流量聚合), `node_health_events` (健康事件).
|
||||
@@ -94,6 +95,12 @@ Frontend:
|
||||
* 必须指定 `tunnel_target_addr`(内网目标地址,如 `192.168.1.100:8080`)和 `tunnel_target_protocol`(`http` 或 `https`)。
|
||||
* 发布配置时,Server 自动将此上游渲染为 `http://127.0.0.1:{relay_vhost_port}`,Agent 依据 Host 头由 frps 路由。
|
||||
|
||||
* **Pages 与上游关联**:
|
||||
* `proxy_routes.upstream_type = 'pages'` 时,必须指定 `pages_project_id`。
|
||||
* 被引用的 Pages 项目必须启用,且必须存在当前激活部署。
|
||||
* Pages 部署包必须作为 Server 本地文件保存,数据库只保存部署元数据与文件清单;禁止把静态资源内容写入 `config_versions.support_files_json`。
|
||||
* 发布配置时,Server 将 Pages 上游渲染为 OpenResty `root` + `try_files` 静态服务,并保留网站规则已有的 HTTPS、WAF、PoW、Basic Auth、限流与缓存配置。
|
||||
|
||||
* **TunnelRelay 节点配置**:
|
||||
* `nodes.node_type = 'tunnel_relay'` 时,新增字段 `relay_bind_port`、`relay_vhost_http_port`、`relay_auth_token` 必须有合理默认值。
|
||||
* `relay_bind_port` 默认 7000,`relay_vhost_http_port` 默认 8080。
|
||||
@@ -163,6 +170,11 @@ v1-v7 视为历史初始基线,不再维护逐版本升级文件。v8-v17 是
|
||||
- CRUD tunnel 实体(创建、查询、更新、删除)。
|
||||
- Token 管理(生成、轮换)。
|
||||
- 强制同步(触发 Client 立即拉取新配置)。
|
||||
* **Admin Pages 管理 API** - `/api/pages/*`,要求 Admin Session。
|
||||
- CRUD Pages 项目。
|
||||
- 上传 zip 部署包、查看部署历史、激活部署、删除非激活部署。
|
||||
* **Agent Pages 下载 API** - `/api/agent/pages/*`,使用 `X-Agent-Token` 认证。
|
||||
- Agent 仅能按激活配置引用的部署 ID 拉取静态部署包,不提供任意文件读取或远程命令入口。
|
||||
* 总览与节点详情优先使用专用聚合接口。
|
||||
* 管理端变更类接口统一使用 `POST`;只读接口使用 `GET`。
|
||||
* 管理端继续复用现有登录、角色与 Session。
|
||||
@@ -184,6 +196,9 @@ v1-v7 视为历史初始基线,不再维护逐版本升级文件。v8-v17 是
|
||||
* 读取 WAF 规则组、规则组引用的 IP 组与网站绑定关系,并在发布快照中保存可回放数据。
|
||||
* 自动型 WAF IP 组只能由 Server 定时任务读取请求日志并执行 Expr 布尔规则,OpenResty Lua 与 Agent 不得直接访问请求日志库或执行自动挖掘逻辑。
|
||||
* 发布版本不得展开 WAF IP 组成员;Agent 必须通过独立的 IP 组 checksum 差异同步和 WebSocket 增量广播维护本地 `waf_ip_groups.json`。
|
||||
* **Pages 配置扩展**:区分上游类型,为 `upstream_type = 'pages'` 的代理规则生成 Pages 部署快照。
|
||||
* OpenResty 侧:将 Pages 上游渲染为本地静态目录 `root` 与 `try_files`,不得渲染 `proxy_pass`。
|
||||
* Agent 侧:在应用 OpenResty 配置前,必须确保引用的 Pages 部署包已下载、checksum 校验通过并解压到 `pages_dir`。
|
||||
* **内网穿透配置扩展**:区分上游类型,为 `upstream_type = 'tunnel'` 的代理规则生成独立的 tunnel 配置数据。
|
||||
* OpenResty 侧:将 tunnel 上游自动渲染为 `http://127.0.0.1:{relay_vhost_port}`,必须保留原始 `Host` 请求头。
|
||||
* Tunnel 侧:为每个 Client 生成完整的 relay 列表与 frpc 代理定义(frpc proxy 配置)。
|
||||
@@ -209,6 +224,7 @@ Agent 必须满足:
|
||||
* 发现新版本时先备份旧文件。
|
||||
* 写入主配置、路由配置与必要证书文件。
|
||||
* 写入 WAF/PoW 运行时配置,并确保 WAF Lua 资源由 Agent 统一管理。
|
||||
* 如果激活配置引用 Pages 部署,必须通过 Agent API 拉取部署包,校验配置快照中的 SHA-256 checksum,安全解压并原子切换本地当前部署目录;zip 路径不得逃逸 `pages_dir`,不得接受符号链接。
|
||||
* WAF IP 组同步必须按组增量更新,不得在每次心跳或每次同步中传输全部 IP 组。
|
||||
* 写入新配置后执行 `openresty -t -c <main_config_path>`,再 reload;reload 发现运行时未启动时允许直接启动 OpenResty。
|
||||
* 周期性运行时健康检查不得调用 `openresty -t`,避免健康探针触发 upstream 域名同步解析;应优先请求本地 `openresty_observability_port` 上的 `/openflare/stub_status`,以 HTTP `200 OK` 作为 OpenResty 主进程和 worker 正在提供服务的判断依据。
|
||||
|
||||
@@ -168,6 +168,7 @@ OpenResty 性能参数与缓存参数继续统一保存在 `Option` 表。当前
|
||||
| `OPENFLARE_NODE_IP` | 节点 IP,可覆盖 `agent.json` | 空 |
|
||||
| `OPENFLARE_DATA_DIR` | Agent 数据目录,可覆盖 `agent.json` | 空 |
|
||||
| `OPENFLARE_OPENRESTY_PATH` | OpenResty 二进制路径,可覆盖 `agent.json` | 空 |
|
||||
| `OPENFLARE_PAGES_DIR` | Pages 静态部署目录,可覆盖 `agent.json` | 空 |
|
||||
| `OPENFLARE_HEARTBEAT_INTERVAL` | 心跳间隔,可覆盖 `agent.json` | 空 |
|
||||
| `OPENFLARE_REQUEST_TIMEOUT` | 请求超时,可覆盖 `agent.json` | 空 |
|
||||
| `OPENFLARE_OPENRESTY_OBSERVABILITY_PORT` | 本地观测端口,可覆盖 `agent.json` | 空 |
|
||||
@@ -201,6 +202,7 @@ OpenResty 性能参数与缓存参数继续统一保存在 `Option` 表。当前
|
||||
| `lua_dir` | Lua 脚本与静态资源写入目录 | 否 | `data_dir/etc/nginx/lua` |
|
||||
| `openresty_lua_dir` | OpenResty 配置中读取 Lua 的目录 | 否 | 同 `lua_dir` |
|
||||
| `runtime_config_dir` | Agent 运行时配置写入目录,如 `pow_config.json` | 否 | `data_dir/etc/openflare` |
|
||||
| `pages_dir` | Pages 静态部署包解压与当前部署目录 | 否 | `data_dir/var/lib/openflare/pages` |
|
||||
| `mmdb_path` | WAF GeoIP mmdb 文件路径 | 否 | `data_dir/etc/openflare/GeoLite2-Country.mmdb` |
|
||||
| `mmdb_update_interval` | WAF GeoIP mmdb 更新间隔 | 否 | `86400000` 毫秒 |
|
||||
| `mmdb_download_url` | WAF GeoIP mmdb 下载地址 | 否 | 内置 GeoLite2 Country 下载地址 |
|
||||
@@ -218,6 +220,7 @@ OpenResty 性能参数与缓存参数继续统一保存在 `Option` 表。当前
|
||||
* 未配置 `openresty_path` 时默认调用 `openresty`。
|
||||
* Agent 周期性健康检查会请求 `http://127.0.0.1:<openresty_observability_port>/openflare/stub_status`,不再通过高频 `openresty -t` 判断运行时健康;配置应用、启动恢复和 reload 前校验仍会执行 `openresty -t -c <main_config_path>`。
|
||||
* Agent 会初始化并定期更新 `mmdb_path`,供 OpenResty WAF Lua 执行国家级地域规则;更新失败只记录警告,不阻断同步或 reload。
|
||||
* 当激活配置引用 Pages 部署时,Agent 会在应用 OpenResty 配置前,将部署包下载、校验并解压到 `pages_dir`,OpenResty 通过该目录服务静态文件。
|
||||
* 如果 `agent.json` 不存在,但 `OPENFLARE_SERVER_URL` 与 Token 等环境变量足够,Agent 可以直接启动;两者同时存在时环境变量优先。
|
||||
* Agent 未配置 `node_ip` 时,会优先通过 `https://realip.cc` 获取真实出口公网 IP,适配 Docker/NAT 场景;该请求失败时,才退回本机网卡探测并优先选择公网 IPv4。
|
||||
* Agent 自动探测到私网 `node_ip` 时,Server 会在注册/心跳阶段优先保留 Agent 直连来源的公网地址,避免 NAT/多网卡场景误登记内网网卡地址。
|
||||
@@ -334,6 +337,7 @@ go run .
|
||||
"cert_dir": "/var/lib/openflare-agent/etc/nginx/certs",
|
||||
"lua_dir": "/var/lib/openflare-agent/etc/nginx/lua",
|
||||
"runtime_config_dir": "/var/lib/openflare-agent/etc/openflare",
|
||||
"pages_dir": "/var/lib/openflare-agent/var/lib/openflare/pages",
|
||||
"heartbeat_interval": 10000,
|
||||
"request_timeout": 10000
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user