乐趣区

关于kubernetes:Nextjs解决axios获取真实ip问题

前言

上篇文章中我应用了 ip2region 获取到了 ip 归属地,然而我发现我的框架 next.js 通过 k8s 公布到生产环境之后发现获取的 ip 是 pod 的 ip 而不是实在的外网 ip,上面就来谈谈如何解决!

操作

首先我想到的是可能是阿里云 ACK 本人的问题,于是问了他们客服之前机器人给了上面的解决方案:

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

在 data 中增加上面内容:

compute-full-forwarded-for: "true" 
forwarded-for-header: "X-Forwarded-For" 
use-forwarded-headers: "true" 
enable-real-ip: "true"

设置好即失效,通过!

3、查看 deploy 无状态的 nginx-ingress-controller 日志中展现是不是实在 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 []

通过下面显示,发现每次应用的 pod 的 ip 都是 axios 申请的,实在的都是客户端浏览器申请的,这是为啥呢???

剖析

于是我就开始剖析起造成的起因,因为客户端浏览器发动的申请就是实在的 ip,服务端 next.js 中的 axios 发动的申请就是 pod 的 ip,再联合之前 next.js 遇到的 cookie 问题,我终于破案了!

神思之蛙始终摸你肚子!

浏览器申请 ( 实在 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 属地:中国 |0| 江苏省 | 南京市 | 电信

总结

1、首先排除是阿里云 ACK 的问题
2、剖析后才晓得是 next.js 应用 axios 导致的,批改申请头即可解决。

退出移动版