- README 默认英文:README.en.md → README.md(英文为默认),中文移至 README.zh-CN.md,语言切换链接同步 - 恢复被删除的 docs/en/ 英文文档(git 历史 cc5e53c5^),删除 4 篇已废弃文件 - 英文导航 config.ts 对齐中文结构(新增 Deployment/Changelog 侧栏,同步 Guide/Design 条目) - 翻译 15 篇中文新增文档:guide 5 篇(certificates/pages-usage/proxy-config/uptime-kuma/zone-domain-migration)+ design 10 篇(zone-design/cloudflare-pointing/waf-orchestration/origin-error-page/edge-cache-design/pages-design/logstore/kuma-design/login-captcha/observability 三篇) - en 首页更新(新增 Pages 特性、tagline 同步);changelog 英文入口指向中文版 - vitepress 构建验证:43 个英文页面全部渲染 注意:29 篇旧英文文档为恢复版,部分内容(如 deployment/server、reference/configuration)可能落后于中文,需后续逐篇同步
6.2 KiB
WAF Auto IP Group Expressions
Automatic IP groups are used to aggregate metrics from request logs on a per-client-IP basis, using Expr expressions to determine if an IP should be added to the group. Automatic IP groups can be referenced by IP blacklists or whitelists in WAF rule groups; during publication, the Server only writes the referenced IP group ID to waf_config.json, while IP group members are synchronized independently by the Agent into the local runtime files.
Configuration Structure
The configuration of an automatic IP group is a JSON object:
{
"lookback_minutes": 60,
"rules": [
{
"name": "Single IP High-Frequency 404 Scanning",
"expr": "request_count > 100 && status_404_ratio >= 0.8"
}
]
}
Field Descriptions:
| Field | Type | Role |
|---|---|---|
lookback_minutes |
number | How many minutes of request logs to look back during execution. Defaults to 60 minutes if blank, minimum 5 minutes, maximum 43200 minutes. |
rules |
array | List of automatic rules. If any rule matches, the IP is added to the automatic IP group list. |
rules[].name |
string | Rule name, used only for UI display and error messages. |
rules[].expr |
string | Expr expression, must return a boolean value. |
Evaluation Mechanics
Automatic rules do not evaluate logs request-by-request, but instead aggregate them by client IP first:
- The Server reads request logs from the past
lookback_minutesminutes. - Groups them by normalized IP (
remote_addr). - Computes metrics like request count, 404 count, and direct IP host count for each IP.
- Evaluates
rules[].exprfor each IP. - If an IP matches any rule, it is written to the automatic IP group's IP member list.
Whether a request is "accessing via IP directly" is determined by the Host field in the request logs. If the Host header is an IPv4 or IPv6 literal (e.g., 203.0.113.10, [2001:db8::10], 203.0.113.10:443), it is counted in ip_host_count.
Available Metrics
The following metrics are directly available in Expr expressions:
| Keyword | Type | Role |
|---|---|---|
ip |
string | The client IP currently being evaluated. |
request_count |
number | Total request count of the IP in the lookback window. |
status_404_count |
number | Number of 404 responses returned to the IP in the lookback window. |
status_404_ratio |
number | 404 request ratio, calculated as status_404_count / request_count. |
ip_host_count |
number | Number of requests from the IP using an IP address directly as the Host header. |
ip_host_ratio |
number | Ratio of direct IP address accesses, calculated as ip_host_count / request_count. |
client_error_count |
number | Number of requests returning 4xx status codes. |
server_error_count |
number | Number of requests returning 5xx status codes. |
last_seen_unix |
number | Unix timestamp (in seconds) of the last request from the IP in the lookback window. |
All ratio fields are decimals between 0 and 1. An 80% ratio should be written as 0.8, and 50% as 0.5.
Common Expr Syntax
Automatic IP groups use the Expr syntax. The expression must return a boolean value.
Common Operators:
| Operator | Role | Example |
|---|---|---|
>, >=, <, <= |
Numeric comparison | request_count > 100 |
==, != |
Equality / Inequality | ip != "127.0.0.1" |
&& |
Logical AND | request_count > 100 && status_404_ratio >= 0.8 |
| ` | ` | |
! |
Logical NOT | !(ip == "127.0.0.1") |
in |
Value is in list | ip in ["203.0.113.10", "198.51.100.20"] |
not in |
Value is not in list | ip not in ["127.0.0.1"] |
() |
Grouping controls operator priority | `(request_count > 100 && status_404_ratio >= 0.8) |
Built-in Presets
The management console provides two built-in preset rules that can be added directly and adjusted as needed:
{
"name": "Single IP High-Frequency 404 Scanning",
"expr": "request_count > 100 && status_404_ratio >= 0.8"
}
Meaning: A single IP requests more than 100 times in the lookback window, and the 404 status code ratio is at least 80%.
{
"name": "Single IP Direct IP Access Mismatch",
"expr": "ip_host_count > 50 && ip_host_ratio > 0.5"
}
Meaning: A single IP accesses the server directly using an IP address as the Host header more than 50 times, and this type of access represents more than 50% of its total requests.
Examples
High-frequency 404 scanning:
{
"lookback_minutes": 60,
"rules": [
{
"name": "High-Frequency 404 Scanning",
"expr": "request_count > 100 && status_404_ratio >= 0.8"
}
]
}
Direct IP access mismatch:
{
"lookback_minutes": 30,
"rules": [
{
"name": "Direct IP Access Mismatch",
"expr": "ip_host_count > 50 && ip_host_ratio > 0.5"
}
]
}
Capture both high 4xx and 5xx errors:
{
"lookback_minutes": 120,
"rules": [
{
"name": "Abnormal Error Rates",
"expr": "(client_error_count > 80 && request_count > 100) || server_error_count > 30"
}
]
}
Exclude trusted IPs:
{
"lookback_minutes": 60,
"rules": [
{
"name": "404 Scanning Excluding Trusted IPs",
"expr": "ip not in [\"203.0.113.10\", \"198.51.100.20\"] && request_count > 100 && status_404_ratio >= 0.8"
}
]
}
Usage Recommendations
Start with a shorter lookback window and higher thresholds to monitor matches, then adjust thresholds gradually. The IP Groups page in the management console allows you to click "Test Rule" before saving to view matching IPs in the current window immediately. Once an automatic IP group runs, it overwrites the list of IPs. If you want to permanently whitelist or blacklist certain IPs, add them to a manual IP group instead, and reference both manual and automatic groups in your WAF rule groups.
Updating automatic IP groups does not require publishing configuration versions. Online Agents receive changes via WebSocket and update the local waf_ip_groups.json instantly. If WebSocket is unavailable, the Agent reports its local checksum in heartbeats, and the Server syncs only the mismatched IP groups.