nginx+tomcat 获取正确的remoteAddr
一、问题背景
通过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中代理链的信息被删除。
参考:
- Tomcat 8的RemoteIpValve源码(Valve是阀门的意思),核心处理逻辑是invoke函数
- RemoteIpValve文档
nginx+tomcat 获取正确的remoteAddr相关推荐
- Nginx+Tomcat无法正确获取的域名和ip地址
在利用Nginx作为反向代理服务器的时候,出现一个问题,就是在Tomcat中的web项目获取当前访问域名地址的时候,无法获取到真实的域名或IP地址,进过一系列摸索,最终找到解决办法. 之前的Nginx ...
- PHP、Tomcat获取Nginx代理后的客户端真实IP
PHP.Tomcat获取Nginx代理后的客户端真实IP 文章目录 PHP.Tomcat获取Nginx代理后的客户端真实IP 一.PHP获取Nginx代理后客户端真实IP Nginx配置 PHP配置 ...
- nginx+tomcat+memcached负载均衡
2019独角兽企业重金招聘Python工程师标准>>> nginx+tomcat+memcached负载均衡 负载均衡: 负载均衡是由多台服务器以对称的方式组成一个服务器集合,每台服 ...
- Nginx +Tomcat 实现动静态分离(转)
Nginx +Tomcat 实现动静态分离 动静态分离就是Nginx处理客户端的请求的静态页面(html页面)或者图片,Tomcat处理客户端请求的动态页面(jsp页面),因为Nginx处理的静态页面 ...
- HappyAA服务器部署笔记1(nginx+tomcat的安装与配置)
这是本人的服务器部署笔记.文章名称叫"部署笔记1"的原因是之后我对这个进行了改进之后,会有"部署笔记2","部署笔记3"...循序渐进,估计 ...
- Nginx+Tomcat构筑Web服务器集群
代理服务 代理服务可简单的分为正向代理和反向代理: 正向代理: 用于代理内部网络对Internet的连接请求(如VPN/NAT),客户端指定代理服务器,并将本来要直接发送给目标Web服务器的HTTP请 ...
- SSM+nginx+tomcat+maven+mysql+redis环境搭建及工程全套配置,实现前后端动静分离
目录 前言 服务器环境搭建 windows开发环境 SSM搭建 加入redis(注解形式) nginx与tomcat关联配置,完成前后端连接 前言 本次采用前后端分离模式,前端以html.css.js ...
- Nginx+tomcat配置集群
2019独角兽企业重金招聘Python工程师标准>>> 开发的应用采用F5负载均衡交换机,F5将请求转发给5台hp unix服务器,每台服务器有多个webserver实例,对外提供w ...
- 图文解说:Nginx+tomcat配置集群负载均衡
图文解说:Nginx+tomcat配置集群负载均衡 博客分类: appserver nginxTomcatUbuntuLinux网络应用 作者:niumd Blog:http://ari.iteye ...
最新文章
- JSP 开发环境搭建概述
- 最新!2021中国内地大学ESI排名出炉:326所高校上榜!
- 音频监控叫好又叫座,核心部件拾音器怎么装?
- Java 线程实例二(终止线程、生产者/消费者问题、获取线程状态、获取所有线程、查看线程优先级、中断线程)
- linux fdisk 权限不够,Linux 文件系统结构、磁盘的管理
- 针对ASP.NET MVC的SEO优化笔记
- JavaWeb项目架构之FastDFS分布式文件系统
- 中华优秀传统文化教育的有效渗透
- 基于java(springboot)餐厅点餐系统源码成品(java毕业设计)
- 「Java代码审计」Java代码审计基础知识「一」
- 微信小程序 tab点击切换(不滑动)
- 全球票房73亿的《海王》,是怎么炼成的!
- 作为面试官,如何甄别应聘者的包装程度?
- 2021年总结:回顾这不平凡的一年
- 某大厂外包员工抢了个红包,被要求退回,太侮辱人了!千万别做外包,狗都不如...
- DTI-ATS入门(2):DTI协议纵览
- iOS打开沙盒html,ios 开发中,沙盒目录解释
- 图书信息管理系统(三)
- @Transactional 的使用
- 学习编程,要不要去IT培训机构?自学和去培训班哪种方法更合适?