探索

获取真实ip

时间:2010-12-5 17:23:32  作者:知识   来源:热点  查看:  评论:0
内容摘要:办公室老张昨天又骂人了。他远程连服务器排查故障,查了半天日志,发现所有访问记录里的IP都指向127.0.0.1——本地回环地址。这意味着什么?意味着他看到的全是代理服务器自己的影子,真正的用户来自哪里

办公室老张昨天又骂人了。真实他远程连服务器排查故障,真实查了半天日志,真实发现所有访问记录里的真实IP都指向127.0.0.1——本地回环地址。这意味着什么?真实意味着他看到的全是代理服务器自己的影子,真正的真实用户来自哪里,完全抓瞎。真实

这事不新鲜。真实现在哪个正经业务前面不挂几层代理?真实CDN、Nginx反代、真实云WAF,真实一层套一层。真实你拿个`request.getRemoteAddr()`去取IP,真实取到的真实永远是最近那台代理的地址。就好比你打电话给朋友,真实朋友看到的是总机号码,不是你的手机号。

那真实IP到底藏哪了?HTTP头里。常见的有`X-Forwarded-For`、`X-Real-IP`、`CF-Connecting-IP`。但这里头水很深。`X-Forwarded-For`是个逗号分隔的列表,每经过一层代理,就把上一层IP追加到末尾。比如原始请求来自1.1.1.1,经过代理A(2.2.2.2),再经过代理B(3.3.3.3),最后到你服务器,那这个头就是`1.1.1.1, 2.2.2.2`。最左边的才是用户真实IP——前提是代理没有乱改。

问题恰恰出在这。代理是别人家的,你管不着。有些CDN厂商规范,老老实实追加。有些混蛋节点自作聪明,直接覆盖。更恶心的是,用户自己也能伪造这个头。你如果直接信任`X-Forwarded-For`的第一个值,那随便拿curl发个请求,加上`X-Forwarded-For: 8.8.8.8`,你就以为访问来自谷歌DNS服务器了。这招在防刷、风控场景下简直就是开后门。

我见过最实在的做法,是让可信代理把真实IP写在一个自定义头里,比如`X-Real-IP`,然后后端只认这个头,其他一律忽略。前提是你的代理层完全可控——比如自己搭的Nginx,配置里加一行`proxy_set_header X-Real-IP $remote_addr;`。这样到了后端,取这个头就稳了。但如果你用了第三方CDN,就得看他们文档,确认哪个头是可信的,并且配置好回源时只保留该头,剔除用户伪造的版本。

还有个容易忽略的坑:IPv6。现在很多用户走IPv6,代理转发时如果没处理好,可能把IPv6地址截断或者转换出错。之前我们排查过一个线上问题,用户反馈登录地区乱跳,最后发现是负载均衡器把IPv6的`::ffff:1.2.3.4`这种映射地址当成普通IPv4处理,导致取到的IP段错乱。那段时间风控规则全被绕过去了。

所以你看,取个IP听着简单,实际牵扯到链路信任、协议规范、厂商实现。最靠谱的思路永远是:明确你的可信代理边界,只信任那一段,其余全当垃圾数据。要是实在拿不准,干脆用TCP层的信息——比如在Nginx里记录`$remote_addr`,那是直连你服务器的socket地址,伪造不了。代价是如果用户真挂了多层代理,你就只能看到最后一层了。取舍罢了。

老张后来怎么解决的?他在Nginx层强制覆盖了`X-Real-IP`,后端全改成读这个头。折腾一上午,总算把真实IP捞出来了。他抽了口烟说:早知道当初架构就该这么设计。这话听着耳熟,每次踩坑都是这么总结的。

最近更新
热门排行
copyright © 2026 powered by 力不从心网   sitemap