mirror of
https://github.com/Rain-kl/OpenFlare.git
synced 2026-09-29 22:06:38 +08:00
[优化] 添加自动 IP 组功能,支持按 Expr 规则聚合请求日志并更新 IP 列表
This commit is contained in:
@@ -69,6 +69,7 @@ function sidebarGuide(): DefaultTheme.SidebarItem[] {
|
||||
{ text: '概览', link: '' },
|
||||
{ text: '快速开始', link: 'quick-start' },
|
||||
{ text: '基础使用', link: 'usage' },
|
||||
{ text: 'WAF 自动 IP 组语法', link: 'waf-ip-group-expr' },
|
||||
{ text: 'SSO 登录配置', link: 'sso' },
|
||||
{ text: '发布第一份配置', link: 'first-site' },
|
||||
{ text: '故障排查', link: 'troubleshooting' }
|
||||
|
||||
@@ -165,7 +165,7 @@ Client -> OpenResty server block -> WAF Lua -> named upstream -> Origin
|
||||
|
||||
WAF 在 OpenResty `access_by_lua_file` 阶段执行。规则来自当前激活版本携带的 `waf_config.json`,全局规则组默认生效,网站可叠加自定义规则组。
|
||||
|
||||
WAF IP 组由 Server 管理并在发布时展开到 `waf_config.json`。手动 IP 组直接保存 IP/IP 段列表;自动 IP 组当前只保存配置;订阅 IP 组由 Server 定时任务同步远程文本或 JSON 源。OpenResty Lua 只读取 Agent 落地的运行时 JSON,不直接访问 Server 数据库或远程订阅源。
|
||||
WAF IP 组由 Server 管理并在发布时展开到 `waf_config.json`。手动 IP 组直接保存 IP/IP 段列表;自动 IP 组由 Server 定时任务读取请求日志、按单个 IP 聚合指标并执行 Expr 规则;订阅 IP 组由 Server 定时任务同步远程文本或 JSON 源。OpenResty Lua 只读取 Agent 落地的运行时 JSON,不直接访问 Server 数据库、请求日志或远程订阅源。
|
||||
|
||||
## 核心对象
|
||||
|
||||
|
||||
@@ -139,10 +139,15 @@ WAF 以规则组为配置边界。系统固定一个全局规则组,默认应
|
||||
IP 组约束:
|
||||
|
||||
* 手动 IP 组由管理端直接维护 IP/IP 段列表。
|
||||
* 自动 IP 组当前只保存结构化配置,不执行请求日志挖掘。
|
||||
* 自动 IP 组使用 Expr 语法保存自定义规则,由 Server 定时按单个 IP 聚合请求日志并更新 IP 列表。
|
||||
* 订阅 IP 组由 Server 定时从 HTTP/HTTPS URL 同步,支持文本列表和 JSON 映射。
|
||||
* WAF 运行时不访问数据库;发布时将规则组引用的启用 IP 组展开进完整配置版本。
|
||||
|
||||
自动 IP 组首批内置预设规则:
|
||||
|
||||
* 单个 IP 请求数大于 100,且 404 状态码占比不低于 80%:`request_count > 100 && status_404_ratio >= 0.8`
|
||||
* 单个 IP 通过 IP 地址访问次数大于 50,且通过 IP 地址访问占比大于 50%:`ip_host_count > 50 && ip_host_ratio > 0.5`
|
||||
|
||||
判定顺序:
|
||||
|
||||
* 白名单是放行例外,任意启用规则组命中白名单即放行。
|
||||
|
||||
@@ -18,7 +18,7 @@ Server 发布时必须:
|
||||
2. 读取 Server 侧 OpenResty 主配置、性能参数、缓存参数和必要 Lua 资源。
|
||||
3. 读取域名与证书绑定关系。
|
||||
4. 读取 WAF 全局规则组、自定义规则组、IP 组引用与网站绑定关系。
|
||||
5. 展开 WAF 规则组引用的启用 IP 组,渲染完整 OpenResty 配置与 WAF 运行时配置。
|
||||
5. 使用自动 IP 组最近一次执行后的 IP 列表,并展开 WAF 规则组引用的启用 IP 组,渲染完整 OpenResty 配置与 WAF 运行时配置。
|
||||
6. 计算 `checksum`。
|
||||
7. 写入 `config_versions`。
|
||||
8. 切换激活版本。
|
||||
|
||||
+5
-3
@@ -10,9 +10,10 @@ OpenFlare 是一套自托管的 OpenResty 控制面。它把反向代理网站
|
||||
|
||||
1. [快速开始](./quick-start.md):用 Docker Compose 启动 Server,登录管理端,并接入第一个 Agent。
|
||||
2. [基础使用](./usage.md):了解网站配置、源站、证书、发布、回滚和观测的常见操作。
|
||||
3. [部署说明](../reference/deployment.md):把 Server 和 Agent 放到更接近生产的环境中运行。
|
||||
4. [配置项参考](../reference/configuration.md):查 Server 环境变量、运行时 Option 和 Agent 配置字段。
|
||||
5. [故障排查](./troubleshooting.md):按症状排查登录、数据库、节点同步、OpenResty 应用和前端构建问题。
|
||||
3. [WAF 自动 IP 组语法](./waf-ip-group-expr.md):编写自动 IP 组 Expr 规则,了解关键字含义和预设规则。
|
||||
4. [部署说明](../reference/deployment.md):把 Server 和 Agent 放到更接近生产的环境中运行。
|
||||
5. [配置项参考](../reference/configuration.md):查 Server 环境变量、运行时 Option 和 Agent 配置字段。
|
||||
6. [故障排查](./troubleshooting.md):按症状排查登录、数据库、节点同步、OpenResty 应用和前端构建问题。
|
||||
|
||||
## 按角色查找
|
||||
|
||||
@@ -20,6 +21,7 @@ OpenFlare 是一套自托管的 OpenResty 控制面。它把反向代理网站
|
||||
| --- | --- |
|
||||
| 5 分钟内跑起管理端 | [快速开始](./quick-start.md) |
|
||||
| 发布第一条反向代理配置 | [发布第一份配置](./first-site.md) |
|
||||
| 编写自动 IP 组规则 | [WAF 自动 IP 组语法](./waf-ip-group-expr.md) |
|
||||
| 接入或重装节点 Agent | [接入 Agent](../reference/agent.md) |
|
||||
| 从源码启动 Server | [启动 Server](../reference/server.md) |
|
||||
| 配置 GitHub 或 OIDC 登录 | [SSO 登录配置](./sso.md) |
|
||||
|
||||
+2
-1
@@ -81,7 +81,8 @@ HTTPS 按域名绑定证书,而不是按整个网站统一强制启用。
|
||||
安全防护统一从管理端侧边栏的 **WAF** 入口进入:
|
||||
|
||||
* WAF 页面维护全局规则组和自定义规则组。全局规则组始终应用到全部网站;自定义规则组可以在规则组内一键选择网站,也可以在网站详情的 `WAF` 分区绑定。
|
||||
* 点击 WAF 页面中的 **管理 IP 组** 可以进入独立 IP 组页面。手动 IP 组直接维护 IP/IP 段;自动 IP 组当前保存配置但暂不执行日志挖掘;订阅 IP 组可从远程文本或 JSON 源定时同步。
|
||||
* 点击 WAF 页面中的 **管理 IP 组** 可以进入独立 IP 组页面。手动 IP 组直接维护 IP/IP 段;自动 IP 组使用 Expr 规则按单个 IP 聚合请求日志并定时更新名单;订阅 IP 组可从远程文本或 JSON 源定时同步。
|
||||
* 自动 IP 组页面提供两个预设:单个 IP 请求数大于 100 且 404 占比不低于 80%;单个 IP 通过 IP 地址访问次数大于 50 且该访问占比大于 50%。保存后可点击 **立即执行** 验证规则效果,语法见 [WAF 自动 IP 组规则语法](./waf-ip-group-expr.md)。
|
||||
* 在 WAF 规则组的黑白名单中,IP 维度既可以直接添加 IP/IP 段,也可以引用已有 IP 组。发布时 Server 会把启用 IP 组展开到 WAF 运行时配置。
|
||||
* `PoW` 是规则组内的一个配置 Tab,位于 `黑白名单` 与 `拦截返回` 之间,复用站点已有 PoW 执行逻辑,可将当前 PoW 配置应用到全部网站或当前规则组绑定的网站。
|
||||
* 网站详情页不再单独编辑 PoW 规则,只展示全局 WAF 规则组并绑定自定义 WAF 规则组。PoW 的启用范围和规则内容应回到 WAF 页面统一维护。
|
||||
|
||||
@@ -0,0 +1,161 @@
|
||||
# WAF 自动 IP 组规则语法
|
||||
|
||||
自动 IP 组用于从请求日志中按单个客户端 IP 聚合指标,再用 Expr 表达式判断是否把该 IP 加入组内名单。自动 IP 组可以被 WAF 规则组的 IP 黑名单或白名单引用;发布配置时,Server 会把启用 IP 组展开到 `waf_config.json`。
|
||||
|
||||
## 配置结构
|
||||
|
||||
自动 IP 组的配置是一个 JSON 对象:
|
||||
|
||||
```json
|
||||
{
|
||||
"lookback_minutes": 60,
|
||||
"rules": [
|
||||
{
|
||||
"name": "单 IP 404 高频扫描",
|
||||
"expr": "request_count > 100 && status_404_ratio >= 0.8"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
字段说明:
|
||||
|
||||
| 字段 | 类型 | 作用 |
|
||||
| --- | --- | --- |
|
||||
| `lookback_minutes` | number | 每次执行时回看多少分钟内的请求日志。未填写时默认 60 分钟,最小 5 分钟,最大 43200 分钟。 |
|
||||
| `rules` | array | 自动规则列表。任意一条规则命中时,该 IP 会进入自动 IP 组名单。 |
|
||||
| `rules[].name` | string | 规则名称,只用于界面展示和错误提示。 |
|
||||
| `rules[].expr` | string | Expr 表达式,必须返回布尔值。 |
|
||||
|
||||
## 执行口径
|
||||
|
||||
自动规则不是逐条请求判断,而是先按单个客户端 IP 聚合:
|
||||
|
||||
1. Server 读取最近 `lookback_minutes` 分钟内的请求日志。
|
||||
2. 按 `remote_addr` 归一化后的 IP 分组。
|
||||
3. 为每个 IP 计算请求数、404 数、直连 IP Host 次数等指标。
|
||||
4. 逐个 IP 执行 `rules[].expr`。
|
||||
5. 只要某个 IP 命中任意规则,就写入该自动 IP 组的 `IP / IP 段` 列表。
|
||||
|
||||
Host 是否为“通过 IP 访问”按请求日志中的 `Host` 字段判断:如果 Host 是 IPv4 或 IPv6 字面量,例如 `203.0.113.10`、`[2001:db8::10]`、`203.0.113.10:443`,就计入 `ip_host_count`。
|
||||
|
||||
## 可用关键字
|
||||
|
||||
表达式中可以直接使用以下字段:
|
||||
|
||||
| 关键字 | 类型 | 作用 |
|
||||
| --- | --- | --- |
|
||||
| `ip` | string | 当前正在判断的客户端 IP。 |
|
||||
| `request_count` | number | 当前 IP 在回看窗口内的总请求数。 |
|
||||
| `status_404_count` | number | 当前 IP 在回看窗口内返回 404 的请求数。 |
|
||||
| `status_404_ratio` | number | 404 请求占比,计算方式为 `status_404_count / request_count`。 |
|
||||
| `ip_host_count` | number | 当前 IP 通过 IP 地址作为 Host 访问的请求数。 |
|
||||
| `ip_host_ratio` | number | 通过 IP 地址访问的占比,计算方式为 `ip_host_count / request_count`。 |
|
||||
| `client_error_count` | number | 当前 IP 返回 4xx 状态码的请求数。 |
|
||||
| `server_error_count` | number | 当前 IP 返回 5xx 状态码的请求数。 |
|
||||
| `last_seen_unix` | number | 当前 IP 在回看窗口内最后一次请求的 Unix 秒级时间戳。 |
|
||||
|
||||
比例字段都是 `0` 到 `1` 之间的小数。80% 应写成 `0.8`,50% 应写成 `0.5`。
|
||||
|
||||
## Expr 常用写法
|
||||
|
||||
自动 IP 组使用 Expr 语法,当前表达式必须返回布尔值。
|
||||
|
||||
常用运算符:
|
||||
|
||||
| 写法 | 作用 | 示例 |
|
||||
| --- | --- | --- |
|
||||
| `>`、`>=`、`<`、`<=` | 数值比较 | `request_count > 100` |
|
||||
| `==`、`!=` | 相等或不相等 | `ip != "127.0.0.1"` |
|
||||
| `&&` | 并且 | `request_count > 100 && status_404_ratio >= 0.8` |
|
||||
| `||` | 或者 | `status_404_ratio >= 0.8 || server_error_count > 20` |
|
||||
| `!` | 取反 | `!(ip == "127.0.0.1")` |
|
||||
| `in` | 判断值是否在列表中 | `ip in ["203.0.113.10", "198.51.100.20"]` |
|
||||
| `not in` | 判断值是否不在列表中 | `ip not in ["127.0.0.1"]` |
|
||||
| `()` | 分组控制优先级 | `(request_count > 100 && status_404_ratio >= 0.8) || server_error_count > 50` |
|
||||
|
||||
## 内置预设
|
||||
|
||||
管理端内置两个预设规则,可以直接添加后再按需调整:
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "单 IP 404 高频扫描",
|
||||
"expr": "request_count > 100 && status_404_ratio >= 0.8"
|
||||
}
|
||||
```
|
||||
|
||||
含义:单个 IP 在回看窗口内请求数大于 100,并且 404 状态码占比不低于 80%。
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "单 IP 直连访问异常",
|
||||
"expr": "ip_host_count > 50 && ip_host_ratio > 0.5"
|
||||
}
|
||||
```
|
||||
|
||||
含义:单个 IP 通过 IP 地址作为 Host 访问的次数大于 50,并且这种访问占比大于 50%。
|
||||
|
||||
## 示例
|
||||
|
||||
高频 404 扫描:
|
||||
|
||||
```json
|
||||
{
|
||||
"lookback_minutes": 60,
|
||||
"rules": [
|
||||
{
|
||||
"name": "高频 404 扫描",
|
||||
"expr": "request_count > 100 && status_404_ratio >= 0.8"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
IP 直连访问异常:
|
||||
|
||||
```json
|
||||
{
|
||||
"lookback_minutes": 30,
|
||||
"rules": [
|
||||
{
|
||||
"name": "IP 直连访问异常",
|
||||
"expr": "ip_host_count > 50 && ip_host_ratio > 0.5"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
同时捕获高 4xx 与高 5xx:
|
||||
|
||||
```json
|
||||
{
|
||||
"lookback_minutes": 120,
|
||||
"rules": [
|
||||
{
|
||||
"name": "异常错误率",
|
||||
"expr": "(client_error_count > 80 && request_count > 100) || server_error_count > 30"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
排除可信 IP:
|
||||
|
||||
```json
|
||||
{
|
||||
"lookback_minutes": 60,
|
||||
"rules": [
|
||||
{
|
||||
"name": "排除可信 IP 的 404 扫描",
|
||||
"expr": "ip not in [\"203.0.113.10\", \"198.51.100.20\"] && request_count > 100 && status_404_ratio >= 0.8"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
## 使用建议
|
||||
|
||||
先用较短的回看窗口和较高阈值观察命中结果,再逐步调整阈值。自动 IP 组执行后会覆盖该组的 IP 列表;如果要长期保留某些地址,建议放入手动 IP 组,并在 WAF 规则组中同时引用手动组和自动组。
|
||||
|
||||
自动 IP 组更新后不会立即改变 Agent 上的运行时配置。需要重新发布并激活配置版本,Agent 才会拉取新的 `waf_config.json`。
|
||||
@@ -160,6 +160,7 @@ v1-v7 视为历史初始基线,不再维护逐版本升级文件。从 v8 起
|
||||
* 发布时读取全部启用的 `proxy_routes`。
|
||||
* 同时读取 OpenResty 主配置参数、反代性能参数与缓存参数。
|
||||
* 读取 WAF 规则组、规则组引用的 IP 组与网站绑定关系,并在发布快照中保存可回放数据。
|
||||
* 自动型 WAF IP 组只能由 Server 定时任务读取请求日志并执行 Expr 布尔规则,OpenResty Lua 与 Agent 不得直接访问请求日志库或执行自动挖掘逻辑。
|
||||
* 生成完整 OpenResty 配置。
|
||||
* 计算 `checksum`。
|
||||
* 写入 `config_versions`。
|
||||
|
||||
+20
-2
@@ -36,9 +36,27 @@ OpenFlare 的管理端 API 与 Agent API 都使用 JSON。
|
||||
| `POST` | `/api/waf/ip-groups` | 创建 IP 组 |
|
||||
| `POST` | `/api/waf/ip-groups/:id/update` | 更新 IP 组 |
|
||||
| `POST` | `/api/waf/ip-groups/:id/delete` | 删除 IP 组;已被规则组引用时会拒绝 |
|
||||
| `POST` | `/api/waf/ip-groups/:id/sync` | 立即同步订阅型 IP 组 |
|
||||
| `POST` | `/api/waf/ip-groups/:id/sync` | 立即同步订阅型 IP 组或立即执行自动型 IP 组 |
|
||||
|
||||
IP 组 `type` 支持 `manual`、`automatic`、`subscription`。订阅格式支持 `text` 与 `json`:文本格式按行解析 IP/IP 段并忽略空行和 `#` 开头的注释;JSON 格式可通过映射规则选择数组,默认读取根数组。
|
||||
IP 组 `type` 支持 `manual`、`automatic`、`subscription`。自动型 IP 组的 `auto_config` 是 JSON 对象,当前支持:
|
||||
|
||||
```json
|
||||
{
|
||||
"lookback_minutes": 60,
|
||||
"rules": [
|
||||
{
|
||||
"name": "单 IP 404 高频扫描",
|
||||
"expr": "request_count > 100 && status_404_ratio >= 0.8"
|
||||
},
|
||||
{
|
||||
"name": "单 IP 直连访问异常",
|
||||
"expr": "ip_host_count > 50 && ip_host_ratio > 0.5"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
自动规则使用 Expr 语法,表达式必须返回布尔值。规则按单个 IP 的请求日志聚合指标计算,可用字段包括 `ip`、`request_count`、`status_404_count`、`status_404_ratio`、`ip_host_count`、`ip_host_ratio`、`client_error_count`、`server_error_count`、`last_seen_unix`。完整语法和字段含义见 [WAF 自动 IP 组规则语法](../guide/waf-ip-group-expr.md)。订阅格式支持 `text` 与 `json`:文本格式按行解析 IP/IP 段并忽略空行和 `#` 开头的注释;JSON 格式可通过映射规则选择数组,默认读取根数组。
|
||||
|
||||
## 鉴权
|
||||
|
||||
|
||||
Reference in New Issue
Block a user