当前位置: 首页 > ai >正文

K8S中应用无法获取用户真实ip问题排查

现象

领导反馈生产环境的用户ip有问题。登陆到这个页面,发现是所有的用户ip都是172.30.94.97,这是个内部网络ip.

排查过程

1 登陆到应用前端nginx, 查看nginx的请求日志

172.30.94.97 - - [17/Jul/2024:02:02:54 +0000] "POST /***/notify/my-page HTTP/1.1" 200 182 "/report/home?type=2&id=2612&lang=zh_CN" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36" "10.72.44.200"
172.30.94.97 - - [17/Jul/2024:02:02:54 +0000] "POST /***/notify/my-page HTTP/1.1" 200 182 "/home?lang=zh_CN" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36" "10.49.140.102"
172.30.94.97 - - [17/Jul/2024:02:02:56 +0000] "POST /***/msg/notify/my-page HTTP/1.1" 200 59 "/user/message/info?lang=zh_CN" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36" "10.13.52.192"

发现第一列展示的ip正好是我们的Java应用代码拿到的iP,而真实的ip展示在最后一列

2 查看nginx的日志输出格式。第一列取的是remote_addr变量,说明这个变量是有问题的 。我们要取的是最后一列http_x_forwarded_for变量

log_format  main   '$remote_addr - $remote_user [$time_local] "$request" ''$status $body_bytes_sent "$http_referer" ''"$http_user_agent" "$http_x_forwarded_for"';

3 查看Java代码获取客户ip的逻辑。Java代码从6个Header变量中依次找可以用的ip。

    public static String getClientIP(HttpServletRequest request, String... otherHeaderNames) {String[] headers = new String[]{"X-Forwarded-For", "X-Real-IP", "Proxy-Client-IP", "WL-Proxy-Client-IP", "HTTP_CLIENT_IP", "HTTP_X_FORWARDED_FOR"};if (ArrayUtil.isNotEmpty(otherHeaderNames)) {headers = (String[])ArrayUtil.addAll(new String[][]{headers, otherHeaderNames});}return getClientIPByHeader(request, headers);} 

4 查看nginx传递过来了哪些Header变量。nginx传递过来了X-Real-IP和X-Forwarded-For,其中X-Real-IP取的是有问题的remote_addr,正好我们Java代码取到的是这个变量。X-Forwarded-For没有值。

location ~ ^/(admin-api|rpc-api)/ {client_max_body_size 32m;proxy_set_header Host $host;proxy_set_header X-Real-IP $remote_addr;proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;proxy_pass http://***:30001;
}

5 根据第二步的分析,将remote_addr修改为http_x_forwarded_for
6 重启nginx,问题解决

K8S网络拓扑

在这里插入图片描述
所有的外部流量一定会通过一个ingress controller进入到K8S的内部。ingress controller的一个常见实现是Nginx,正好我们的k8s选择的就是Nginx。也就是说我们的业务前端nginx前面还有一个nginx。所以我们的前端nginx的remote_addr拿到的是k8s入口ingress的内部ip地址。

总结

用户请求经过两层nginx转发才到达后端java业务应用。remote_addr仅存储上一个转发节点的ip,所以我们的业务应用一直拿的是ingress的ip。http_x_forwarded_for存储的是原始用户的请求ip。

http://www.xdnf.cn/news/13499.html

相关文章:

  • 数据链抗干扰
  • DNS小结
  • 避免在 iOS 和 Android 的 WebView 中长按出现复制框等默认行为
  • 手机解压 7z 文件全攻略
  • 【全志V821_FoxPi】2-2 切换为spi nand方案启动
  • HTML5 浮动
  • 统计可分解整数的数量
  • leetcode1584. 连接所有点的最小费用-medium
  • 2025低空经济区的安全与应急控制专题研讨会(SECOLZ 2025)
  • DDoS攻防实战:从应急脚本到AI云防护系统
  • 2025年智慧城市与管理工程国际会议(ICSCME 2025)
  • 第二章——线性表之循环链表、静态链表
  • 机械ERP需要解决的几个问题?关于非标机械行业物料编码,如何提升建立效率的说明!
  • 【深度学习】深度学习中的张量:从多维数组到智能计算单元
  • GO语言使用gorm的dbresolver插件实现数据库读写分离
  • iOS开发申请组播/广播权限​
  • 【C/C++】long long 类型传参推荐方式
  • asio之静态互斥量
  • 【PmHub面试篇】集成 Sentinel+OpenFeign实现网关流量控制与服务降级相关面试题解答
  • 远程io模块在汽车流水线的应用
  • 深度学习工具四剑客:Anaconda、Jupyter、PyTorch与CUDA详解
  • 达梦数据库dsc集群+异步主备
  • DeviceNet转Modbus RTU网关在玻璃制造中的关键应用
  • 如何制定兼容多个项目的整体时间计划?
  • Vue.js $emit的介绍和简单使用
  • 【leetcode-合并两个有序链表】
  • Codeforces Round 1029 (Div. 3)
  • C语言数据结构笔记6:使用宏和指针来设置和操作嵌套在结构体中的联合体数组的特定位
  • OC学习—Block初探(简易版)
  • 【实战指南】前端项目Nginx配置全流程:从打包部署到解决跨域/路由循环问题