From b48414e1fe48ea1dbbcfb0a0982fb1da012fdf5d Mon Sep 17 00:00:00 2001 From: ryan Date: Fri, 26 Jun 2026 21:17:43 +0800 Subject: [PATCH] docs: update --- docs/DEPLOYMENT.md | 335 ---------------------------------- docs/deployment/agent.md | 10 +- docs/deployment/deployment.md | 7 +- docs/deployment/server.md | 2 +- docs/design/waf-design.md | 5 +- docs/guide/waf-usage.md | 7 +- 6 files changed, 19 insertions(+), 347 deletions(-) delete mode 100644 docs/DEPLOYMENT.md diff --git a/docs/DEPLOYMENT.md b/docs/DEPLOYMENT.md deleted file mode 100644 index b71ef3b2..00000000 --- a/docs/DEPLOYMENT.md +++ /dev/null @@ -1,335 +0,0 @@ -# wavelet 部署指南 - -本文档详细介绍了 **wavelet** 脚手架系统在不同业务阶段的部署方案,涵盖从**最小化单机部署**到**最大化高可用分布式部署**的全生命周期架构。 - ---- - -## 一、 系统组件概览 - -在部署系统前,请了解各运行组件及其角色: - -| 组件名称 | 运行命令/形式 | 职责说明 | 必选/可选 | -| :--- | :--- | :--- | :--- | -| **HTTP API 服务** | `bin/openflare-server api` | 接收并处理前端及第三方的 RESTful API 请求 | **必选** | -| **异步任务工作进程** | `bin/openflare-server worker` | 消费并处理异步队列任务(如邮件发送、清理上传文件等) | **必选** | -| **定时任务调度器** | `bin/openflare-server scheduler` | 定时向 Redis 队列下发 Cron 任务(仅负责触发,不负责执行) | **必选** | -| **前端服务 (Node.js)** | `pnpm start` | 提供 React/Next.js 页面服务(在分离部署时使用) | 分离模式必选 | -| **PostgreSQL** | 关系型主数据库 | 存储用户、系统配置、认证源、任务执行记录等核心数据 | **必选** | -| **Redis** | 缓存与消息队列中间件 | 存储 Session 会话、临时缓存以及 Asynq 异步任务队列数据 | **必选** | -| **ClickHouse** | 分析型数据库 | 存储历史数据同步或进行高性能分析 | 可选 | -| **对象存储 (S3)** | 兼容 S3 的云存储/私有云 | 存放用户上传的静态文件、图片等 | 可选 | - ---- - -## 二、 部署配置准备 - -系统在启动前会从当前目录加载 `config.yaml` 配置文件。 -生产环境部署前,请复制 `config.example.yaml` 为 `config.yaml`,并至少确认以下关键参数的配置: - -```yaml -app: - env: "production" # 生产环境标识 - addr: ":8000" # API 服务监听端口 - session_secret: "prod-random-secret" # 极其重要的加密密钥,首发启动后不可更改 - session_domain: ".yourdomain.com" # 跨域共享 Session 时需配置 - -database: - host: "db.yourdomain.com" - port: 5432 - username: "postgres" - password: "YOUR_DB_PASSWORD" - database: "refreshing" - -redis: - addrs: - - "redis.yourdomain.com:6379" - password: "YOUR_REDIS_PASSWORD" -``` - ---- - -## 三、 方案一:最小部署 — 单机嵌入式极简版 (推荐) - -此部署方案将**前端静态网页全部直接打入 Go 后端二进制文件中**,极大地简化了部署运维,是中小型应用、内部系统、SaaS 早期阶段的首选。 - -### 📊 架构设计 -- **服务载体**:单台云服务器 (1核2G 即可)。 -- **依赖服务**:在一台机器上启动轻量级 PostgreSQL 与 Redis(可采用 Docker 部署)。 -- **进程管理**:在一台机器上直接拉起打包好的 Go 单文件,并分别运行 `api`、`worker`、`scheduler` 进程。 -- **前端托管**:Go 服务直接在 8000 端口承载前端的所有页面,不需要额外配置 Node.js 生产服务器。 - -### 🛠️ 步骤说明 - -#### 1. 单机依赖服务初始化 (使用 Docker Compose) -在机器上准备以下 `docker-compose.yml` 快速启动 PostgreSQL 和 Redis: -```yaml -version: '3.8' -services: - postgres: - image: postgres:15-alpine - container_name: refreshing-db - environment: - POSTGRES_USER: postgres - POSTGRES_PASSWORD: YOUR_DB_PASSWORD - POSTGRES_DB: refreshing - ports: - - "5432:5432" - volumes: - - ./data/pg:/var/lib/postgresql/data - restart: always - - redis: - image: valkey/valkey:8.0-alpine - container_name: refreshing-redis - command: valkey-server --requirepass YOUR_REDIS_PASSWORD - ports: - - "6379:6379" - volumes: - - ./data/redis:/data - restart: always -``` -执行命令启动: -```bash -docker compose up -d -``` - -#### 2. 前后端一键嵌入式打包 -在开发或编译机上,运行编译指令: -```bash -make build-embedded -``` -该命令会自动完成前端的静态编译导出 (`frontend/out`)、复制到 Go 后端目录,最后使用 `-tags embed_frontend` 生成后端单文件: -- 产物路径:`bin/openflare-server` - -#### 3. 进程管理 (使用 Systemd) -将 `bin/openflare-server` 拷贝到生产服务器 `/usr/local/bin/openflare-server`,并为 `api`、`worker` 和 `scheduler` 配置 Systemd 管理服务。 - -新建 API 进程服务文件 `/etc/systemd/system/openflare-api.service`: -```ini -[Unit] -Description=Refreshing API Service -After=network.target - -[Service] -Type=simple -User=root -WorkingDirectory=/app -ExecStart=/usr/local/bin/openflare-server api -Restart=always -RestartSec=5 - -[Install] -WantedBy=multi-user.target -``` -同理,新建 Worker 服务 `/etc/systemd/system/openflare-worker.service`(将命令改为 `openflare-server worker`),以及 Scheduler 服务 `/etc/systemd/system/openflare-scheduler.service`(将命令改为 `openflare-server scheduler`)。 - -启动并启用所有服务: -```bash -systemctl daemon-reload -systemctl enable --now refreshing-api refreshing-worker refreshing-scheduler -``` - -#### 4. 配置 Nginx 证书 -配置 Nginx 作为反向代理并启用 HTTPS 证书: -```nginx -server { - listen 80; - server_name yourdomain.com; - return 301 https://$host$request_uri; -} - -server { - listen 443 ssl http2; - server_name yourdomain.com; - - ssl_certificate /path/to/cert.crt; - ssl_certificate_key /path/to/cert.key; - - location / { - proxy_pass http://127.0.0.1:8000; - proxy_set_header Host $host; - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_set_header X-Forwarded-Proto $scheme; - } -} -``` - ---- - -## 四、 方案二:标准部署 — 前后端物理分离架构 - -此方案中前端与后端彻底解耦。前端采用 SSR/ISR (Next.js Node 服务) 运行,后端采用独立的 API 服务运行。 - -### 📊 架构设计 -- **前端部署**:单独部署到 Node.js 托管环境(如多台前端机器或 Vercel/Cloudflare Pages)。 -- **后端部署**:多台后端云服务器,统一指向云数据库 RDS 与云缓存 Redis。 -- **通信方式**:前后端通过 Nginx 规则路由或独立域名(如 `app.yourdomain.com` 访问前端,`api.yourdomain.com` 访问后端)进行跨域通信。 - -### 🛠️ 步骤说明 - -#### 1. 部署后端 Go 服务 -1. 编译后端: - ```bash - go build -o bin/openflare-server main.go - ``` -2. 在后端服务器上,同样使用 Systemd 或 Docker 守护启动 `openflare-server api`、`openflare-server worker` 和 `openflare-server scheduler`。 -3. 配置后端 Nginx 将客户端 API 请求(如 `/api/...`)反向代理至后端绑定的端口(如 `:8000`)。 - -#### 2. 部署前端 Next.js 服务 -1. 前端服务器环境确保已安装 Node.js 和 pnpm。 -2. 安装依赖并编译生产版本: - ```bash - cd frontend - pnpm install - pnpm build - ``` -3. 使用 PM2 守护前端 Node.js 服务运行。新建 `ecosystem.config.js`: - ```javascript - module.exports = { - apps: [ - { - name: 'refreshing-frontend', - script: 'node_modules/next/dist/bin/next', - args: 'start -p 3000', - instances: 'max', - exec_mode: 'cluster', - env: { - NODE_ENV: 'production', - WAVELET_BACKEND_URL: 'https://api.yourdomain.com' - } - } - ] - }; - ``` - 启动前端服务: - ```bash - pm2 start ecosystem.config.js - ``` - -#### 3. 跨域与 Cookie 说明 -- 若前后端使用**不同子域名**部署(例如 `app.yourdomain.com` 和 `api.yourdomain.com`),必须在 `config.yaml` 中将 `app.session_domain` 显式设置为顶级域名(`.yourdomain.com`),以确保 Session Cookie 可以在子域间顺利透传。 -- 在跨域状态下,前端请求必须配置 `withCredentials: true`,API 端的跨域中间件(`corsMiddleware`)会自动将该域添加至允许源中。 - ---- - -## 五、 方案三:最大部署 — 企业级高可用分布式架构 (Max) - -当系统面临高并发流量、海量后台任务或极高的可用性要求时,需要将所有组件拆分为无状态水平扩容,并引入高可用的云基础设施。 - -### 📊 架构设计图 -``` - ┌────────────────────────┐ - │ 域名 / 负载均衡器 │ - │ (SLB / Cloudflare) │ - └──────────┬─────────────┘ - │ - ┌──────────────────┴──────────────────┐ - ▼ ▼ - ┌─────────────────────┐ ┌─────────────────────┐ - │ 前端集群 │ │ 后端 API 集群 │ - │ (Next.js Node) │ │ (Go 无状态实例) │ - │ [弹性扩容 / 8台+] │ │ [弹性扩容 / 8台+] │ - └─────────────────────┘ └──────────┬──────────┘ - │ - ┌────────────────────────────────────────┼────────────────────────────────────────┐ - ▼ ▼ ▼ - ┌───────────────────┐ ┌───────────────────┐ ┌───────────────────┐ - │ 异步 Worker 集群 │ │ 定时 Scheduler │ │ S3 对象存储集群 │ - │ (多节点并发处理) │ │ (主备模式,限单节点)│ │(R2/MinIO/AWS S3) │ - └─────────┬─────────┘ └─────────┬─────────┘ └───────────────────┘ - │ │ - └───────────────────┬────────────────────┘ - │ - ┌───────────────────┴────────────────────┐ - ▼ ▼ - ┌───────────────────────────────────┐ ┌───────────────────────────────────┐ - │ Redis 哨兵/集群 │ │ PG 主从读写分离集群 │ - │ (高可用缓存/Asynq 队列) │ │ (RDS Primary-Replica) │ - └───────────────────────────────────┘ └───────────────────────────────────┘ -``` - -### ⚙️ 最大部署配置要点 - -#### 1. 数据库高可用 (主从读写分离) -在 `config.yaml` 中配置 `database` 的主库写与从库读: -```yaml -database: - enabled: true - host: "pg-primary.yourdomain.com" # 主库地址(写) - port: 5432 - username: "postgres" - password: "YOUR_DB_PASSWORD" - database: "refreshing" - # 配置读写分离只读副本(GORM 自动轮询读,支持配置多个从库) - replicas: - - host: "pg-replica-1.yourdomain.com" - port: 5432 - username: "postgres" - password: "YOUR_DB_PASSWORD" - - host: "pg-replica-2.yourdomain.com" - port: 5432 - username: "postgres" - password: "YOUR_DB_PASSWORD" -``` - -#### 2. Redis 高可用 (哨兵/Sentinel 或集群) -- **Sentinel 哨兵模式**:通过配置 `redis.master_name` 启用,SDK 会自动监视 Master 的主备切换。 -- **Cluster 集群模式**:将 `redis.cluster_mode` 设为 `true`,并提供所有集群节点的 `addrs`。 -```yaml -redis: - addrs: - - "redis-node-1.yourdomain.com:6379" - - "redis-node-2.yourdomain.com:6379" - - "redis-node-3.yourdomain.com:6379" - cluster_mode: true -``` - -#### 3. 对象存储与缓存分离 (S3 + Local Cache) -高可用集群下,本地文件系统不再可共享。文件存储必须启用 S3 兼容服务,并在多节点间开启本地高速磁盘缓存加速读取: -```yaml -s3: - enabled: true - endpoint: "https://your-r2-or-s3-id.r2.cloudflarestorage.com" - region: "auto" - bucket: "refreshing-assets" - access_key_id: "YOUR_S3_KEY" - secret_access_key: "YOUR_S3_SECRET" - local_cache: - enabled: true # 开启本地磁盘缓存 - cache_dir: "/data/s3_cache" # 本地高性能 SSD 挂载点 -``` - -#### 4. 后端进程横向拆分部署 -- **API 集群**:启动数十个甚至上百个 `wavelet api` 无状态容器。它们可以通过负载均衡器直接挂载,支持随时弹性缩容扩容。 -- **Worker 集群**:启动多个 `wavelet worker` 容器。因为 `Asynq` 基于 Redis 分布式处理,多个 Worker 进程可以安全地同时运行并竞抢同一队列的异步任务,自动保障任务的并发吞吐能力。 -- **Scheduler 独占**:**【注意】** 为避免重复触发定时 Cron 任务,`wavelet scheduler` 定时调度器进程**同一时间应仅运行单个活跃实例**(主备高可用可以通过容器平台的单实例保障或 K8s Job 机制来限制实例数为 1)。 - -#### 5. ClickHouse 高并发同步 -在大数据量、高频支付结算场景下,开启 ClickHouse 以接收系统的历史数据同步,通过定时器把 PostgreSQL 的压力转移到 ClickHouse 列式存储中。 -```yaml -clickhouse: - enabled: true - hosts: - - "ch-node-1.yourdomain.com:9000" - - "ch-node-2.yourdomain.com:9000" -``` - -#### 6. OpenTelemetry 分布式链路追踪 -最大部署架构必须引入链路追踪(Jaeger 或 OTel Collector)以便排查节点间请求延迟或网络问题。 -在生产环境,通过配置 OTel 将 Span 发送至公共日志分析平台。 -```yaml -otel: - sampling_rate: 0.05 # 开启 5% 的流量追踪采样率以减少开销 -``` - ---- - -## 六、 部署方案对比与选择建议 - -| 指标维度 | 方案一:最小单机嵌入版 | 方案二:标准前后端分离版 | 方案三:最大高可用分布式版 | -| :--- | :--- | :--- | :--- | -| **支持流量/并发** | 1,000 ~ 5,000 QPS (视机器性能) | 5,000 ~ 20,000 QPS | 20,000 ~ 100,000+ QPS (无限扩展) | -| **服务器数量** | 1 台 | 3 ~ 5 台 | 10 台以上集群 | -| **运维复杂度** | 极简 (只需部署一个程序) | 中等 (需维护 Node 和 Go 两套环境) | 较高 (K8s/多组件集群维护) | -| **适合场景** | 个人项目、内部系统、SaaS 早期起步 | 正常线上运营项目、有中等规模团队 | 大型企业级应用、高并发核心交易系统 | diff --git a/docs/deployment/agent.md b/docs/deployment/agent.md index c4ba69fe..a2976c41 100644 --- a/docs/deployment/agent.md +++ b/docs/deployment/agent.md @@ -57,7 +57,7 @@ curl -fsSL https://raw.githubusercontent.com/Rain-kl/OpenFlare/main/scripts/inst --docker ``` -安装脚本在本地安装模式下会下载最新 Agent,默认写入 `/opt/openflare-agent`,生成 `agent.json`,并在 Linux + systemd 环境创建 `openflare-agent.service`。 +安装脚本在本地安装模式下会下载最新 Agent,默认写入 `/opt/openflare-agent`,生成 `agent.json`,自动检测并创建低权限系统账号 `openflare`(将整个安装目录赋权给该用户),并在 Linux + systemd 环境创建 `openflare-agent.service` 服务。该服务将以 `openflare` 普通用户运行,并通过 Linux Capabilities(`CAP_NET_BIND_SERVICE`)保障其监听特权端口(如 80、443)的能力。 支持参数: @@ -131,6 +131,12 @@ docker run -d --name openflare-agent --restart unless-stopped \ ghcr.io/rain-kl/openflare-agent:latest ``` +> [!NOTE] +> **非 Root 安全加固运行** +> Agent 容器内部已完成安全加固,在启动后会统一以低权限非 root 用户 `openflare` 运行。 +> 容器已内置了 `cap_net_bind_service` 内核能力,使得低权限进程依然能够正常监听宿主机的 `80` 和 `443` 特权端口。 +> 同时,OpenResty 运行时所需的各种临时路径(包括 PID 路径、各类临时缓存目录如 `client_body_temp_path`、`proxy_temp_path` 等)都由 Agent 控制器动态渲染并自动重定向至挂载的 `/data` 数据目录,彻底避免在非 root 权限运行时写入默认系统路径而导致的权限拒绝错误(Permission Denied)。 + ## 启动与验证 systemd 环境: @@ -214,5 +220,5 @@ curl -fsSL https://raw.githubusercontent.com/Rain-kl/OpenFlare/main/scripts/unin | --- | --- | | `agent_token 和 discovery_token 不能同时为空` | 检查 `agent.json` 至少配置了一个 Token | | 节点一直离线 | 在 Agent 节点执行 `curl -I http://your-server:3000`,确认 Server 地址可达 | -| OpenResty 没有启动 | 查看 `journalctl -u openflare-agent`,确认 `openresty_path` 可执行且 80/443 端口未被占用 | +| OpenResty 没有启动 | 查看 `journalctl -u openflare-agent`,确认 `openresty_path` 可执行,80/443 端口未被占用,且运行用户(如 `openflare`)对数据目录具有读写权限 | | 发布后重复失败 | Agent 会阻断同一 `version + checksum` 的重复应用;需要修正配置后重新发布,或激活旧版本回滚 | diff --git a/docs/deployment/deployment.md b/docs/deployment/deployment.md index 1aeccb12..e2bd9bae 100644 --- a/docs/deployment/deployment.md +++ b/docs/deployment/deployment.md @@ -85,7 +85,7 @@ cp .env.example .env # 编辑 .env,至少修改 APP_SESSION_SECRET 与数据库密码 docker compose up -d docker compose ps -docker compose logs -f wavelet +docker compose logs -f openflare ``` 首次访问 `http://localhost:3000`,默认账号为 `root` / `123456`。登录后请立即修改默认密码。 @@ -117,6 +117,9 @@ go run main.go all Docker 部署是 Agent 推荐的部署方式。Docker 部署时直接运行 Agent 镜像,该镜像基于 OpenResty 镜像制作,内置 Agent 控制器与 OpenResty 二进制。未显式配置 `node_ip` 时,Agent 会优先通过第三方 API 获取真实出口 IP,避免把 Docker 网桥地址登记为节点 IP。 +> [!NOTE] +> Agent 镜像已完成非 Root 安全加固,统一以普通用户 `openflare` 权限运行,通过内核 capabilities 授权(`cap_net_bind_service`)监听 80/443 特权端口,并自动重定向临时文件和 PID 路径至挂载数据卷以防止写入冲突。 + 挂载配置文件: ```bash @@ -143,7 +146,7 @@ docker run -d --name openflare-agent --restart unless-stopped \ ## Agent 接入(脚本安装) -除了 Docker 部署外,也支持通过安装脚本将 Agent 部署在本地宿主机上。 +除了 Docker 部署外,也支持通过安装脚本将 Agent 部署在本地宿主机上。安装脚本会自动在本地 Linux 系统中注册低权限的 `openflare` 服务账号,并将 systemd 服务配置为以该用户身份运行,利用 Linux Capabilities 安全地监听 80/443 特权端口。 使用 `discovery_token` 自动注册: diff --git a/docs/deployment/server.md b/docs/deployment/server.md index 13a188da..f8cb47de 100644 --- a/docs/deployment/server.md +++ b/docs/deployment/server.md @@ -79,7 +79,7 @@ docker run -d \ -e DB_ENABLED=false \ -e SQLITE_PATH='/data/openflare.db' \ -e LOG_LEVEL='info' \ - ghcr.io/rain-kl/openflare:latest + ghcr.io/rain-kl/openflare-server:latest ``` 启动参数说明: diff --git a/docs/design/waf-design.md b/docs/design/waf-design.md index 5a81c46b..e04259fc 100644 --- a/docs/design/waf-design.md +++ b/docs/design/waf-design.md @@ -110,8 +110,7 @@ flowchart TD D -- 是 (匹配成功) --> E[放行请求 - ALLOW] D -- 否 --> F{匹配到国家/地区地域白名单?} F -- 是 (匹配成功) --> E - F -- 否且已配置任意白名单 --> H - F -- 否且未配置白名单 --> G{匹配到 IP 黑名单 / 黑名单 IP 组?} + F -- 否 --> G{匹配到 IP 黑名单 / 黑名单 IP 组?} G -- 是 (匹配成功) --> H[阻断请求 - BLOCK] G -- 否 --> I{匹配到国家/地区地域黑名单?} I -- 是 (匹配成功) --> H @@ -124,7 +123,7 @@ flowchart TD ### 2. 判决步骤细则 1. **白名单前置**: - 为了防止误杀以及保障核心回源流量(如搜索引擎蜘蛛、CDN 回源 IP、办公区出口)的顺畅,WAF **优先匹配 IP 白名单与地域白名单**。一旦白名单匹配成功,直接绕过后续的所有黑名单检测和 CC 挑战,立刻放行。只要当前生效规则组配置了任意白名单,请求未命中全部白名单时会被拦截,白名单在这种情况下表现为准入名单。 + 为了防止误杀以及保障核心回源流量(如搜索引擎蜘蛛、CDN 回源 IP、办公区出口)的顺畅,WAF **优先匹配 IP 白名单与地域白名单**。一旦白名单匹配成功,直接绕过后续的所有黑名单检测和 CC 挑战,立刻放行。如果请求未命中白名单,则继续向下进行黑名单检测及其他后续判定。 2. **黑名单强力阻断**: 如果在白名单判定中未被捕获,请求将进入黑名单漏斗。一旦请求源 IP 命中 IP 黑名单、命中引用的黑名单 IP 组、或是处于被禁止的国家/地区范围内,Lua 引擎立即将 `ngx.ctx.openflare_waf_blocked` 标记设为 `true`。 3. **输出响应**: diff --git a/docs/guide/waf-usage.md b/docs/guide/waf-usage.md index c7dc6e81..4e27d164 100644 --- a/docs/guide/waf-usage.md +++ b/docs/guide/waf-usage.md @@ -144,8 +144,7 @@ IP 组是进行大批量 IP 过滤的基石。OpenFlare 提供了极富弹性的 │ (否) ▼ 2. 匹配国家 / 省份地域白名单? ────────(是)─────► [ 放行 (ALLOW) ] - │ (否,且已配置任意白名单) ─► [ 拦截 (BLOCK) ] - │ (否,且未配置白名单) + │ (否) ▼ 3. 匹配 IP 黑名单 / 黑名单 IP 组? ──────(是)─────► [ 拦截 (BLOCK) ] ──► 返回自定义状态码与HTML拦截页 │ (否) @@ -167,8 +166,8 @@ IP 组是进行大批量 IP 过滤的基石。OpenFlare 提供了极富弹性的 ## 最佳实践与调优建议 -* **白名单准入语义**:一旦某个生效规则组配置了 IP 白名单、白名单 IP 组或地域白名单,请求必须命中其中至少一条白名单规则才会继续放行;未命中白名单的请求会被拦截。白名单命中后仍会优先绕过后续黑名单与 PoW 检查。 -* **白名单前置与保护**:在部署高强度黑名单或地域屏蔽前,建议首先创建一个「受信任 IP 组」,放入你团队的办公室出口 IP、本地开发 IP 以及可能访问你的第三方回调源站 IP(如微信、支付宝支付回调地址),并在规则组的**白名单**中优先引入。这可以有效防止误杀,但也会让未在白名单内的来源无法访问。 +* **白名单放行语义**:一旦某个生效规则组配置了 IP 白名单、白名单 IP 组或地域白名单,且请求命中了其中至少一条白名单规则,该请求将被直接放行,并优先绕过后续的黑名单与 PoW 检查;未命中的请求则会继续进行黑名单等后续防护校验。 +* **白名单前置与保护**:在部署高强度黑名单或地域屏蔽前,建议首先创建一个「受信任 IP 组」,放入你团队的办公室出口 IP、本地开发 IP 以及可能访问你的第三方回调源站 IP(如微信、支付宝支付回调地址),并在规则组的**白名单**中优先引入。这可以有效防止误杀,确保信任的 IP 即使命中黑名单或 CC 限制也能无阻碍访问。 * **合理微调 PoW 难度**:人机 CC 挑战的哈希碰撞计算(`challenge_difficulty`)是一把双刃剑。 * 难度值 `3`:几乎瞬间完成计算,防 CC 强度低。 * 难度值 `4`:普通手机/低端浏览器在 100~300ms 内完成计算,防护性能良好。