docker:Java通过nginx获取客户端的真实ip地址

问题现象

  • 我们的平台使用Spring Cloud微服务架构,使用Spring Boot构建Java服务,使用google的jib插件打成docker镜像包
  • 我们使用docker虚拟化部署,使用docker-compose统一管理所有服务,包括Java服务和nginx等组件
  • 我们前后端分离,前端通过nginx访问我们的网关(Spring Cloud Gateway),再转发到对应的Java服务
  • 我们需要记录一些基础业务数据变动日志,于是在过滤器里拦截对应请求记录日志
  • 在记录操作的来源ip时,记录了一个172.18.0.x的地址,这个明显不是实际客户端来源的ip

排查解决

  • 我们使用getRemoteAddres(request)获取的ip地址,按理说是能获取到客户端的真实ip地址的
  • 地址不对,想着从request的header里直接获取,参考网上的方法,查看哪个header参数里有ip地址
    log.info("X-Real-IP={}", request.getHeader("X-Real-IP"));log.info("X-Original-Forwarded-For={}", request.getHeader("X-Original-Forwarded-For"));log.info("X-Forwarded-For={}", request.getHeader("X-Forwarded-For"));log.info("x-forwarded-for={}", request.getHeader("x-forwarded-for"));log.info("Proxy-Client-IP={}", request.getHeader("Proxy-Client-IP"));log.info("WL-Proxy-Client-IP={}", request.getHeader("WL-Proxy-Client-IP"));log.info("HTTP_CLIENT_IP={}", request.getHeader("HTTP_CLIENT_IP"));log.info("HTTP_X_FORWARDED_FOR={}", request.getHeader("HTTP_X_FORWARDED_FOR"));
  • 结果发现,只有X-Forwarded-For能获取到地址,还是那个错误的172.18.0.x的地址
    在这里插入图片描述

  • 地址不对,应该是哪里出了问题,可能是docker网络、nginx代理或者gateway网关

  • 进一步排查,这个地址之前看到过,172.1x.0.x,是docker网络生成的ip地址

  • 使用docker命令docker network ls,查看了docker网络后,发现我们确实用的是这个
    在这里插入图片描述

  • 继续查看各个docker服务的ip,确定下这个ip是哪个服务的,具体来说,是nginx的、gateway的,还是具体的这个Java应用的

  • 使用docker exec -it 服务名 /bin/bash进入docker容器内部,使用cat /etc/hosts查看网络配置

  • 对比发现这个ip是nginx服务的,说明获取客户端远程地址时,获取到了nginx的ip
    在这里插入图片描述

  • nginx是决定能获取到正确的客户端请求ip地址的,因为它的log日志输出里,是有来源ip的
    在这里插入图片描述

修改nginx配置

  • 查看了nginx的配置文件default.conf,发现里面没有其他配置,已有的X-Forwarded-For配置为proxy_set_header X-Forwarded-For $proxy_protocol_addr;,这里直接把nginx代理服务自己的地址赋给了X-Forwarded-For,所以我们获取到的是nginx的地址
  • 我们现在需要做的,主要是在主配置文件,添加一行proxy_set_header X-Real-IP $remote_addr;,将客户端的真实ip地址,赋给X-Real-IP
  • 执行命令docker restart nginx,重启nginx使其生效

Java代码

  • Java代码修改也很简单,对应nginx的配置,获取X-Real-IP即可
    public static String getIpAddress(HttpServletRequest request) {String ip = request.getHeader("X-Real-IP");if (StringUtils.isEmpty(ip) || "unknown".equalsIgnoreCase(ip)) {ip = request.getRemoteAddr();}return ip;}
  • 成功获取,结束
    在这里插入图片描述

nginx配置proxy_set_header介绍

在Nginx配置中,proxy_set_header 指令是用于定义向代理服务器传递的请求头字段。该指令专门用于location块中,并且通常配合 proxy_pass 指令一起工作,proxy_pass 指令定义了代理服务器的协议和地址。

基本上,当Nginx作为反向代理服务器时,客户端的请求首先到达Nginx,然后Nginx将这些请求转发到后端的上游服务器。在转发请求时,Nginx可以设置或修改请求头。proxy_set_header 指令正是用来进行这样的设置或修改。

下面是几个proxy_set_header 常见用例:

  • 传递主机名 - 将客户端请求的原主机头信息传递到上游服务器。

    proxy_set_header Host $host;
    
  • 传递真实IP地址 - 将客户端的真实IP地址传递给后端应用,这在后端应用需要记录真实的客户端地址时非常有用。

    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    
  • 传递HTTPS相关信息 - 当Nginx用作SSL终结时,它可以告诉后端应用请求是通过HTTPS或HTTP进行的。

    proxy_set_header X-Forwarded-Proto $scheme;
    
  • 用户的Worker处理状态: 有时,应用程序可能需要知道客户端连接的具体状态。

    proxy_set_header Connection $connection_upgrade;
    

标准的 proxy_set_header 指令使用方法如下:

proxy_set_header Header-Name Header-Value;
  • Header-Name 是你希望设置的HTTP请求头名称。
  • Header-Value 是对应的值,它可能是一个固定的字符串,也可以是Nginx提供的变量,如 $remote_addr$http_user_agent$http_cookie 等。

注意,默认情况下,Nginx会使用某些标准请求头,如HostConnection等,如果你没有明确使用proxy_set_header设置它们,Nginx会传递它的默认值。

在调整Nginx作为反向代理服务器时,正确配置proxy_set_header指令能确保后端服务器可以接收到所需的所有重要信息,提供正确和安全的服务。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/412442.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

ONLYOFFICE:开源、免费、安全,打造定制化办公平台的最佳选择

文章目录 写在前面ONLYOFFICE是什么?ONLYOFFICE的惊艳之处齐全的插件,助你锦上添花部署一款自己的安全可靠的办公平台写在最后 写在前面 说起 Office 办公软件,我想大家最常用的应该就是微软的 Microsoft Office 以及国产的 WPS Office。两款…

关于微信小程序 “扫普通链接二维码打开小程序”动态传递多个参数开发过程记录与总结

前言:项目中需要线下 扫描二维码 进入到小程序指定的页面,二维码中 要动态传递多个参数,接下来看看具体怎么实现,整个过程还比较顺利,特把整个过程中遇到的坑点做以总结。 快速跳转官网文档介绍:扫码打开小…

基于深度学习的实例分割的Web应用

基于深度学习的实例分割的Web应用 1. 项目简介1.1 模型部署1.2 Web应用 2. Web前端开发3. Web后端开发4. 总结 1. 项目简介 这是一个基于深度学习的实例分割Web应用的项目介绍。该项目使用PaddlePaddle框架,并以PaddleSeg训练的图像分割模型为例。 1.1 模型部署 …

shopee选品案例分析:如何在Shopee平台上进行选品并取得成功

在Shopee平台上进行选品是卖家们开设店铺的重要步骤之一。通过分析成功案例,卖家们可以获取灵感和策略,从而更好地进行选品。本文将以一个女装店铺为例,介绍如何在Shopee平台上进行选品并取得成功。 先给大家推荐一款shopee知虾数据运营工具…

Oracle21C + PLSQL Developer 15 + Oracle客户端21安装配置完整图文版

一、Oracle21C PLSQL Developer 15 Oracle客户端文件下载 1、Oracl21C下载地址:Database Software Downloads | Oracle 中国 2、 PLSQL Developer 15下载地址:Registered download PL/SQL Developer - Allround Automations 3、 Oracle 客户端下载地址…

使用composer生成的DMG和PKG格式软件包有何区别

在使用Composer从包源构建软件包时候,有两种不同类型的包:PKG和DMG。你知道两者之间的区别吗? 以及如何选取吗? 每种格式都有各自的优势具体取决于软件包的预期用途以及用于部署软件包的工具。下面我们来了解一下PKG和DMG格式的区别和用途。…

vscode连接远程服务器(傻瓜式教学)

**如何在远程服务器上进行编码呢?vscode!!!**当然,还有很多其他选择,例如sublime、ultraedit等等,这里我们用非常流行的vscode来连接ubuntu服务器做讲解!1、下载vscode 百度搜索vsc…

怎样实现安全便捷的网间数据安全交换?

数据安全交换是指在数据传输过程中采取一系列措施来保护数据的完整性、机密性和可用性。网间数据安全交换,则是需要进行跨网络、跨网段甚至跨组织地进行数据交互,对于数据的传输要求会更高。 大部分企业都是通过网闸、DMZ区、VLAN、双网云桌面等方式实现…

Oracle 实战手册 工作实战经验总结

目录 一、基本的数据库管理 1、数据库的启动和关闭 ​编辑2、如何确定Oracle的版本? 3、如何修改数据库的内存参数 4、修改用户名密码 5、如何查看最大会话数 6、如何修改oracle数据库的用户连接数 7、解锁用户 8、如何获取被锁定的数据库对象 9、如何确定…

如何使用Synology Drive作为文件同步服务器实现云同步Obsidian笔记

文章目录 一、简介软件特色演示: 二、使用免费群晖虚拟机搭建群晖Synology Drive服务,实现局域网同步1 安装并设置Synology Drive套件2 局域网内同步文件测试 三、内网穿透群晖Synology Drive,实现异地多端同步Windows 安装 Cpolar步骤&#…

项目经理进阶之路:如何应对不同阶段的挑战?

最近看到一个帖子,有网友提问,“项目经理的职业发展会经历哪几个阶段?不同阶段需要关注什么?又分别会遇到哪些挑战?“这个帖子引发了广大项目经理们的热议,大家纷纷吐槽,自己遇到了职业瓶颈、询…

redis之单线程和多线程

目录 1、redis的发展史 2、redis为什么选择单线程? 3、主线程和Io线程是怎么协作完成请求处理的? 4、IO多路复用 5、开启redis多线程 1、redis的发展史 Redis4.0之前是用的单线程,4.0以后逐渐支持多线程 Redis4.0之前一直采用单线程的主…