一、问题背景

通过nginx来反向代理客户端请求,经过nginx中转转发给tomcat服务器,但发现tomcat服务器无法获取到正确的remoteAddr客户端地址,每次请求拿到的都是nginx所在服务器的IP

1、在tomcat服务器上查看tomcat服务日志,发现打印的请求日志,remoteAddr都是nginx的IP,而不是客户端的真实IP

## 192.168.200.251是nginx负载均衡服务器的地址
15:08:12 INFO    [tid:166453,Q:W228AFjoBcRQIzvVzOuJ] [L-Android]func=xxxx,remote=192.168.200.251

二、定位过程

1、nginx配置如下

location /myService {proxy_set_header    X-FORWARDED-FOR $remote_addr;proxy_set_header    X-Forwarded-Proto $scheme;proxy_set_header    Host   $http_host;#分发到tomcat服务器,192.168.201.228为tomcat服务器proxy_pass http://192.168.201.228:9900;}

一开始以为是nginx配置有问题,设置了各种参数后,发现不是nginx问题,而是tomcat 的设置影响,在tomcat的conf/server.xml里RemoteIpValve项的InternalProxies

<Engine name="Catalina" defaultHost="localhost"><Host name="localhost" appBase="webapps"unpackWARs="false" autoDeploy="true"<Valve className="org.apache.catalina.valves.AccessLogValve"<!-- for nginx --><Valve className="org.apache.catalina.valves.RemoteIpValve"remoteIpHeader="X-FORWARDED-FOR"protocolHeader="X-FORWARDED-PROTO"internalProxies="192\.168\.*"/></Host>
</Engine>

在使用Nginx代理网络请求时,设置proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for,但是在我的server端(Tomcat,Spring)收到的网络请求中却得不到这个x-forwarded-for的信息,原因是我的代理机器的IP地址与Tomcat RemoteIpValve中配置的默认内部代理地址internalProxies能匹配,于是x-forwarded-for信息被忽略并删除了。
(在server.xml中删除RemoteIpValve的默认配置,或者配置internalProxies为其他地址(如server的地址),就可以在x-forwarded-for中得到代理传输过来的信息。)

三、解决方案

1、将tomcat server.xml的internalProxies修改为nginx的IP,tomcat即可正确处理x-forwarded-for逻辑,获取正确的remoteAddr

<Engine name="Catalina" defaultHost="localhost"><Host name="localhost" appBase="webapps"unpackWARs="false" autoDeploy="true"<Valve className="org.apache.catalina.valves.AccessLogValve"<!-- for nginx --><Valve className="org.apache.catalina.valves.RemoteIpValve"remoteIpHeader="X-FORWARDED-FOR"protocolHeader="X-FORWARDED-PROTO"## 修改internalProxies为nginx的IPinternalProxies="127\.0\.0\.1|192\.168\.200\.251"/></Host>
</Engine>

2、重启tomcat,查看客户端请求日志,可以看到remoteAddr已经是客户端的真实IP而不是nginx的IP了

16:08:12 INFO    [tid:166453,Q:W228AFjoBcRQIzvVzOuJ] [L-Android]func=xxxx,remote=192.168.201.46

四、tomcat RemoteIpValve InternalProxies原理解析

X-Forwarded-For
x-forwarded-for在HTTP Header中,用来记录代理链的IP信息(不包括最后一次的代理)。

RemoteIpValve
Tomcat中的RemoteIpValve的设计意图是根据InternalProxies和TrustedProxies的配置,来过滤代理信息链X-Forwarded-For中的信息,获取代理机器之前的IP地址,并改写RemoteAddress的值。如果没有RemoteIpValve的处理,且有代理转发的情况下,则RemoteAddress永远为代理机器的IP地址,而不是代理机器之前发送数据包机器的IP地址(根据网络情况,可能为实际的用户IP地址)
具体逻辑如下图所示。

初始RemoteAddress为代理机器的IP地址,首先判断是否与InternalProxies匹配,如果不匹配,则RemoterIpValve不会做处理;如果匹配,则根据InternalProxies和TrustedProxies的配置来决定是否改写X-Forwarded-For和RemoteAddress以及X-Forwarded-By。

internalProxies默认情况下是有配置值的(貌似是常见的局域网IP地址),trustedProxies默认为null。而我的内网代理机器和我本机的IP地址都与InternalProxies匹配,则X-Forwarded-For中代理链的信息被删除。

参考:

  1. Tomcat 8的RemoteIpValve源码(Valve是阀门的意思),核心处理逻辑是invoke函数
  2. RemoteIpValve文档

nginx+tomcat 获取正确的remoteAddr相关推荐

  1. Nginx+Tomcat无法正确获取的域名和ip地址

    在利用Nginx作为反向代理服务器的时候,出现一个问题,就是在Tomcat中的web项目获取当前访问域名地址的时候,无法获取到真实的域名或IP地址,进过一系列摸索,最终找到解决办法. 之前的Nginx ...

  2. PHP、Tomcat获取Nginx代理后的客户端真实IP

    PHP.Tomcat获取Nginx代理后的客户端真实IP 文章目录 PHP.Tomcat获取Nginx代理后的客户端真实IP 一.PHP获取Nginx代理后客户端真实IP Nginx配置 PHP配置 ...

  3. nginx+tomcat+memcached负载均衡

    2019独角兽企业重金招聘Python工程师标准>>> nginx+tomcat+memcached负载均衡 负载均衡: 负载均衡是由多台服务器以对称的方式组成一个服务器集合,每台服 ...

  4. Nginx +Tomcat 实现动静态分离(转)

    Nginx +Tomcat 实现动静态分离 动静态分离就是Nginx处理客户端的请求的静态页面(html页面)或者图片,Tomcat处理客户端请求的动态页面(jsp页面),因为Nginx处理的静态页面 ...

  5. HappyAA服务器部署笔记1(nginx+tomcat的安装与配置)

    这是本人的服务器部署笔记.文章名称叫"部署笔记1"的原因是之后我对这个进行了改进之后,会有"部署笔记2","部署笔记3"...循序渐进,估计 ...

  6. Nginx+Tomcat构筑Web服务器集群

    代理服务 代理服务可简单的分为正向代理和反向代理: 正向代理: 用于代理内部网络对Internet的连接请求(如VPN/NAT),客户端指定代理服务器,并将本来要直接发送给目标Web服务器的HTTP请 ...

  7. SSM+nginx+tomcat+maven+mysql+redis环境搭建及工程全套配置,实现前后端动静分离

    目录 前言 服务器环境搭建 windows开发环境 SSM搭建 加入redis(注解形式) nginx与tomcat关联配置,完成前后端连接 前言 本次采用前后端分离模式,前端以html.css.js ...

  8. Nginx+tomcat配置集群

    2019独角兽企业重金招聘Python工程师标准>>> 开发的应用采用F5负载均衡交换机,F5将请求转发给5台hp unix服务器,每台服务器有多个webserver实例,对外提供w ...

  9. 图文解说:Nginx+tomcat配置集群负载均衡

    图文解说:Nginx+tomcat配置集群负载均衡 博客分类: appserver nginxTomcatUbuntuLinux网络应用  作者:niumd Blog:http://ari.iteye ...

最新文章

  1. JSP 开发环境搭建概述
  2. 最新!2021中国内地大学ESI排名出炉:326所高校上榜!
  3. 音频监控叫好又叫座,核心部件拾音器怎么装?
  4. Java 线程实例二(终止线程、生产者/消费者问题、获取线程状态、获取所有线程、查看线程优先级、中断线程)
  5. linux fdisk 权限不够,Linux 文件系统结构、磁盘的管理
  6. 针对ASP.NET MVC的SEO优化笔记
  7. JavaWeb项目架构之FastDFS分布式文件系统
  8. 中华优秀传统文化教育的有效渗透
  9. 基于java(springboot)餐厅点餐系统源码成品(java毕业设计)
  10. 「Java代码审计」Java代码审计基础知识「一」
  11. 微信小程序 tab点击切换(不滑动)
  12. 全球票房73亿的《海王》,是怎么炼成的!
  13. 作为面试官,如何甄别应聘者的包装程度?
  14. 2021年总结:回顾这不平凡的一年
  15. 某大厂外包员工抢了个红包,被要求退回,太侮辱人了!千万别做外包,狗都不如...
  16. DTI-ATS入门(2):DTI协议纵览
  17. iOS打开沙盒html,ios 开发中,沙盒目录解释
  18. 图书信息管理系统(三)
  19. @Transactional 的使用
  20. 学习编程,要不要去IT培训机构?自学和去培训班哪种方法更合适?

热门文章

  1. 《腹盆腔三维可视化系统的设计与实现》阅读
  2. html表格网页自适应居中,web前端:css自适应居中方法总结
  3. MySQL命令行下载安装配置——详细教程
  4. 判断单链表的对称性-链表
  5. java类加载器是什么?
  6. SQLSERVER 数据库多表联查重复值问题
  7. idea去掉中间白线的方法超简单
  8. 这所985高校追回一毕业生博士学历、学位证书!其为公司高管,身家逾20亿元...
  9. go 语言值传递和引用传递
  10. 爬虫获取代理IP并检验可用性与识别指纹