本文分析Next.js应用通过Kubernetes发布后,使用axios获取到Pod内网IP而非客户端真实IP的问题。通过排查阿里云ACK配置,发现需确保Service和Ingress的externalTrafficPolicy为Local,并在Nginx配置中启用转发头。最终解决方案是在Next.js服务端通过axios手动设置X-Forwarded-For请求头,从而正确获取用户真实IP。
前言
上篇文章中我使用了ip2region获取到了ip归属地,但是我发现我的框架next.js通过k8s发布到生产环境之后发现获取的ip是pod的ip而不是真实的外网ip,下面就来谈谈如何解决!
操作
起初,我怀疑这是阿里云ACK(容器服务Kubernetes版)自身的配置问题,于是联系了官方客服寻求建议。客服提供的初步解决方案如下:
ACK容器集群应用Pod如何获取客户端真实IP ACK容器集群Pod如何获取客户端真实IP? 如果您未使用WAF,且集群是通过SLB暴露的业务,请检查Service的YAML文件,确保externaltrafficpolicy为Local模式,该模式下可获取到客户端真实IP。如果集群是通过Ingress暴露的业务,请检查nginx-ingress-lb的externaltrafficpolicy,确保externaltrafficpolicy为Local模式。
如果您使用了WAF,请参见K8s Ingress获取真实IP地址处理。
客服解决方案
在确认上述配置并非问题根源后,客服提供了进一步的排查步骤和解决方案:
1、检查Service中nginx-ingress-lb的外部流量策略是否设置为Local。


经核实,该策略确实已设置为Local,因此排除此项配置错误。
2、配置nginx-configuration。
需要执行以下命令进行配置:
kubectl -n kube-system edit cm nginx-configuration在ConfigMap的data字段中添加以下内容:
compute-full-forwarded-for: "true"
forwarded-for-header: "X-Forwarded-For"
use-forwarded-headers: "true"
enable-real-ip: "true"配置完成后立即生效,经测试该步骤有效。
3、检查部署状态中nginx-ingress-controller的日志,确认日志中显示的IP是否为真实IP。


172.22.32.48 - [172.22.32.48] - - [31/Aug/2023:11:49:00 +0800] "GET /api/space/info/urlCategory/zhangwei HTTP/1.1" 200 20188 "-" "axios/1.5.0" 320 0.059 [seaurl-testapi-seaurl-gatewayserver-svc-7777] 172.22.32.57:7777 20188 0.059 200 9c6a2589d7926d266abe56b6e4b38488 testapi.seaurl.com [] 114.222.247.210 - [114.222.247.210] - - [31/Aug/2023:11:49:01 +0800] "GET /api/space/crud/urlCategory/zhangwei/categoryTreeList HTTP/2.0" 200 20188 "https://test.seaurl.com/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Safari/537.36" 56 0.027 [seaurl-testapi-seaurl-gatewayserver-svc-7777] 172.22.32.57:7777 20188 0.027 200 e165866b16394694c332e82aa47de562 testapi.seaurl.com []
从日志输出可以看出,每次请求中显示的IP均为Pod的内网IP,而axios请求本身是由客户端浏览器发起的。这引发了疑问:为什么会出现这种差异?
分析
我开始深入分析造成这一现象的原因。客户端浏览器直接发起的请求能够携带真实IP,而Next.js应用中通过axios发起的服务端请求却返回了Pod IP。结合之前Next.js处理Cookie时遇到的类似问题,最终找到了根本原因。
请求路径差异导致IP信息不同:
浏览器请求(真实ip)->nginx-ingress-controller->spring cloud gateway
next.js所在的pod中的axios请求(pod ip)->nginx-ingress-controller->spring cloud gateway
问题核心在于:
浏览器发出的请求中,X-Forwarded-For请求头正确携带了外部真实IP;而在Next.js Pod内部,由axios发起的请求并未设置X-Forwarded-For请求头,因此默认使用了Pod的内网IP。
解决方案:
只需在Next.js应用中,通过axios手动设置请求头X-Forwarded-For即可解决此问题。具体实现如下:
export const getServerSideProps = wrapper.getServerSideProps(store => async (ctx) => {
const ip = ctx.req.headers['x-forwarded-for'] || ctx.req.connection.remoteAddress;
axios.defaults.headers.cookie = ctx.req.headers.cookie || null
axios.defaults.headers['X-Forwarded-For'] = ip这样,真实IP就会被正确设置到axios的请求头中,从而完美解决获取真实IP的问题。
IP属地:中国|0|江苏省|南京市|电信
总结
1、首先确认阿里云ACK的配置并非导致问题的原因。
2、经分析确认,问题源于Next.js使用axios发起请求时未正确传递IP信息,通过修改请求头即可解决。
以上就是Next.js解决axios获取真实ip问题方法分析的详细内容,更多关于Next.js axios获取ip的资料请关注本站其它相关文章!