CDN 之后如何拿到真实用户 IP
发布时间:2026-08-02 12:28       
更新时间:2026-08-03 01:49
接了 CDN 之后,Nginx 日志里的访问 IP 全变成节点 IP,真实用户 IP 要从 X-Forwarded-For 头里取——但不能拿来就用,这个头谁都能伪造。
为什么不能直接信
X-Forwarded-For 是链式字段,请求每经过一层代理就追加一段。攻击者完全可以自己构造一个假的 X-Forwarded-For 发请求,服务端如果直接取第一个值,限频、风控、取证就全被带偏了。取值的原则只有一条:只信 CDN 追加的那一段。真实 IP 落进日志不只是好看——限频按它算才准,出了安全事件按它才能溯源,审计报表的口径也靠它,这个数据一旦歪了,建立在它上面的判断会跟着全歪。
Nginx 的正确配置
用 realip 模块,把可信的节点网段列出来,Nginx 会从右往左跳过可信节点,还原出真实 IP:
set_real_ip_from 198.51.100.0/24;
set_real_ip_from 203.0.113.0/24;
real_ip_header X-Forwarded-For;
real_ip_recursive on;
上面的网段只是格式示例,实际填你的 CDN 服务商官方公布的回源网段列表。real_ip_recursive on 的语义是从右往左递归跳过所有可信网段,直到遇到第一个不可信地址为止,那个地址就是真实来源;不开递归只会跳一层,多层代理的场景会取错。配置生效后,$remote_addr 直接就是真实用户 IP,日志格式和业务代码都不用改。CDN 支持透传自定义头的话(主流节点基本都支持),也可以让它把真实 IP 放进专用头,源站只信任这个头,效果等价。两层 CDN 叠加使用的,两个供应商的网段都要列全,漏了一段,那一部分请求就会取错值。
验证与防伪造
改完看日志:tail -f /var/log/nginx/access.log,用手机流量访问站点,日志里出现运营商出口 IP 而不是节点 IP,就说明生效了。防伪造的要点也只有一条:set_real_ip_from 只填 CDN 网段,不要写 0.0.0.0/0 这类放行一切的值。用户绕过 CDN 直连的场景下没有这个头,Nginx 自然用 TCP 层的真实来源地址,不会被伪造值污染。业务侧做风控规则时同样记住这个边界:判断逻辑别把 CDN 网段当可疑来源误杀。