必须先配置realip模块解析真实ip,再用$realip_remote_addr定义cdn专用日志格式,并分离日志文件或通过map标记来源,最后利用结构化日志进行pv、ip、状态码等统计分析。

要让 Nginx 准确记录 CDN 回源流量中的真实客户端 IP,并支持后续高效统计分析,不能只改日志格式,必须先确保真实 IP 能被正确识别和传递。否则日志里写的还是 CDN 节点的 IP,所有统计都会失真。
确保真实客户端 IP 被正确解析
Nginx 默认的 `$remote_addr` 是直接连接它的上一级(比如 CDN 节点)的 IP,不是用户真实 IP。要拿到真实 IP,需配合 CDN 厂商的转发规则启用 realip 模块:• 在 http 或 server 块中,按顺序配置以下三项(顺序不能错):
- set_real_ip_from:填 CDN 官方公布的回源 IP 段(如腾讯云、阿里云、Cloudflare 各不相同,必须查最新文档)
-
real_ip_header:指定 CDN 传来的头字段名,例如
X-Real-IP、True-Client-IP或Cf-Connecting-IP - real_ip_recursive on:开启递归解析,应对多层代理场景(比如 CDN + WAF)
⚠️ 注意:漏掉某个 CDN IP 段,或把 set_real_ip_from 写在 real_ip_header 后面,会导致对应请求的 `$remote_addr` 无法更新为真实 IP。
定义面向 CDN 回源的日志格式
真实 IP 解析成功后,用 `$realip_remote_addr`(Nginx ≥ 1.11.0)替代默认的 `$remote_addr`,并补充 CDN 相关字段便于区分和过滤:推荐在 http 块中添加:
log_format cdn_log '$realip_remote_addr - $remote_user [$time_local] '
'"$request" $status $body_bytes_sent '
'"$http_referer" "$http_user_agent" '
'cdn_ip=$remote_addr cdn_header="$http_x_forwarded_for"';
说明:
-
$realip_remote_addr:已解析的真实用户 IP(核心) -
cdn_ip=$remote_addr:保留原始连接 IP,用于确认是否来自 CDN 节点 -
cdn_header="$http_x_forwarded_for":记录原始 XFF 头内容,辅助排查伪造或异常链路 - 字段间用空格或固定分隔符(如
|),方便后续用awk、cut或日志系统解析
为 CDN 流量单独启用访问日志
避免与直连流量混在一起,建议在 server 或 location 块中为 CDN 配置独立日志文件:例如,在 CDN 回源专用 server 块中:
access_log /var/log/nginx/cdn_access.log cdn_log;
如果 CDN 和直连共用一个 server,可通过条件判断分流:
- 利用 CDN 固定回源 IP 段做匹配:
if ($remote_addr ~ "^101\.32\.\d+\.\d+$") { ... }(不推荐 if,更稳妥用 map) - 或用
map提前标记来源:map $remote_addr $is_cdn { default 0; 101.32.0.0/16 1; 111.161.64.0/19 1; } log_format cdn_log '... $is_cdn';
基于日志做基础统计分析
日志格式结构化后,Linux 命令即可快速完成常见统计:常用命令示例(假设日志路径为 /var/log/nginx/cdn_access.log):
- 统计真实 PV:
wc -l /var/log/nginx/cdn_access.log - Top 10 真实 IP:
awk '{print $1}' /var/log/nginx/cdn_access.log | sort | uniq -c | sort -nr | head -10 - 各状态码分布:
awk '{print $9}' /var/log/nginx/cdn_access.log | sort | uniq -c - 提取含特定 CDN 头的请求:
grep "cdn_ip=101\.32\." /var/log/nginx/cdn_access.log
若需长期分析,可接入 ELK、Grafana Loki 或轻量级工具如 goaccess,它们能自动识别空格分隔日志并生成可视化报表。











