Files
re-xxm/deploy/nginx/README.md

105 lines
3.8 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 访问统计与真实来源 IP
看板新增了基础访问统计(PV/UV)。前端在页面访问时通过
`POST /api/visit`(`navigator.sendBeacon`)上报,服务端先写入进程内缓冲、
每分钟批量落库到 `visit` 表(迁移 v7)。`/system` 系统状态页展示近 30 天
PV/UV 与 Top 页面。
统计按客户端 IP 去重,因此**必须在反代层还原真实客户端 IP**。
## 链路与 socket 对端
```text
浏览器 → 域名 → CDN(Cloudflare/EdgeOne) → 公网 EIP → 10.10.8.x(云服务器内网)
→ 宿主机 nginx → proxy_pass http://127.0.0.1:8080 → 容器
```
容器内 socket 对端经端口映射 SNAT 后是 Docker 网关(如 `172.17.0.1`),
不是真实客户端。因此真实 IP 只能来自 nginx 注入的请求头,且有三条来源:
| 场景 | nginx 处理 |
|---|---|
| 域名直接解析到公网 EIP | `$remote_addr` 即客户端,nginx 直接写 `X-Real-IP` |
| 经 Cloudflare | `realip` + `CF-Connecting-IP`(仅当对端属于 CF 网段才采信) |
| 经 EdgeOne | `realip` + `EO-Connecting-IP`(仅当对端属于 EdgeOne 网段才采信) |
应用只读 `X-Real-IP`,且**仅当 socket 对端属于可信代理网段**
(默认回环 + RFC1918 + Docker 网段,可配置)时才采信,否则回退到对端。
这样直连 EIP 的请求即使伪造 `CF-Connecting-IP` / `EO-Connecting-IP` /
`X-Forwarded-For` 也无法污染统计。
> 关键:用 `realip` 模块按 CDN 网段校验,而不是无条件相信 CDN 头。
> 若无条件相信,任何能直连公网 EIP 的人都能伪造来源 IP。
## 文件
| 文件 | 用途 |
|---|---|
| `reaction-board.conf` | 站点 `server {}`,反代到 `127.0.0.1:8080` 并注入真实 IP 头 |
| `realip-cloudflare.conf` | Cloudflare 场景,放在 `http {}` 内 |
| `realip-edgeone.conf` | EdgeOne 场景,放在 `http {}` 内 |
| `update-cloudflare-ips.sh` | 生成 Cloudflare 网段清单 `cloudflare-ips.conf` |
| `update-edgeone-ips.sh` | 由运维维护的 CIDR 清单生成 `edgeone-ips.conf` |
按实际来源**二选一**引入对应的 `realip-*.conf`(放在 `nginx.conf` 的
`http {}` 内),再 `include` 站点配置。
## Cloudflare
```nginx
# nginx.conf 的 http {} 内
include /etc/nginx/realip-cloudflare.conf;
include /etc/nginx/conf.d/reaction-board.conf;
```
```bash
sudo bash deploy/nginx/update-cloudflare-ips.sh
```
Cloudflare 的 IP 段变化很少,建议加 cron 每月刷新一次。
## EdgeOne
EdgeOne 节点网段会变动,需从 EdgeOne 控制台或 API 获取后维护成 CIDR 清单:
```bash
# source 为每行一个 CIDR 的清单
sudo bash deploy/nginx/update-edgeone-ips.sh /path/to/edgeone-cidrs.txt
```
```nginx
# nginx.conf 的 http {} 内
include /etc/nginx/realip-edgeone.conf;
include /etc/nginx/conf.d/reaction-board.conf;
```
若无法自动同步网段,可退化为:在安全组/防火墙只放行 EdgeOne 节点访问源站,
此时可放宽为直接采信 `EO-Connecting-IP`;但**同时保留直连公网 EIP 访问**的
场景下,仍建议使用 `realip` 网段校验。
## 应用侧配置
```jsonc
{
"web": {
"track": {
"enabled": true,
"header_order": ["X-Real-IP", "X-Forwarded-For"],
"trusted_proxies": [
"127.0.0.0/8", "::1/128",
"10.0.0.0/8", "172.16.0.0/12", "192.168.0.0/16", "169.254.0.0/16",
"fc00::/7", "fe80::/10"
],
"count_bots": false,
"flush_seconds": 60,
"keep_days": 180,
"max_hits_per_ip_path_per_day": 0
}
}
}
```
- `flush_seconds`:内存缓冲落库周期;设为 `0` 可关闭后台刷新(仅调试用)。
- `count_bots`:是否统计命中常见爬虫/监控 UA 的请求,默认过滤。
- `max_hits_per_ip_path_per_day`:单个(IP, 页面, 日期)计数上限,`0` 表示不限。
- `keep_days`:保留天数,后台按日清理更早的记录。