Tomcat:“X-Forwarded-For”不适用于负载均衡器

Posted

技术标签:

【中文标题】Tomcat:“X-Forwarded-For”不适用于负载均衡器【英文标题】:Tomcat: 'X-Forwarded-For' doesn't work with load balancer 【发布时间】:2020-07-04 17:47:42 【问题描述】:

我们目前正在使用 Tomcat 7 更新 76 进行冗余服务器设置(2 个服务器 + 1 个负载平衡器)。为了满足我们公司的日志记录要求,我们正在尝试获取远程服务器的 IP,它实际上发送请求,而不是负载均衡器的 IP。不幸的是,我们无法让它与以下文档一起使用:

https://tomcat.apache.org/tomcat-7.0-doc/api/org/apache/catalina/valves/RemoteIpValve.html https://tomcat.apache.org/tomcat-7.0-doc/api/org/apache/catalina/valves/AccessLogValve.html https://tomcat.apache.org/tomcat-7.0-doc/config/valve.html#Remote_IP_Valve

我们使用以下配置进行访问日志记录和远程阀门:

<Valve className="org.apache.catalina.valves.RemoteIpValve" internalProxies="xxx\.xxx\.xxx\.7|xxx\.xxx\.xxx\.8|xxx\.xxx\.xxx\.9"  remoteIpHeader="X-Forwarded-For" />
<Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
prefix="access_log." suffix=".log"
pattern="%org.apache.catalina.AccessLog.RemoteAddrr %l %u %t &quot;%r&quot; %s %b" 
requestAttributesEnabled="true" />

设置了请求标头“X-Forwarded-For”,并通过wireshark分析了负载平衡器。但是,我们仍然只能获得负载均衡器的 IP,而不是远程客户端的 IP。配置的IP地址已经检查过,并且是正确的。

【问题讨论】:

您使用的是什么负载均衡器?它可能被配置为不插入 XFF 标头 负载均衡器用wireshark测试过,显示对应的header字段。很难进一步研究负载均衡器的配置,因为它是由另一个提供商管理的。 使用Request Dumper Filter 来查看Tomcat 收到了什么,它会回答LB 是否发送XFF 标头。顺便说一句,还有其他调试方法,我只是提供一个想法。 我们现在启用了请求转储过滤器。来自负载均衡器的请求包括以下行:header=x-forwarded-for=yyy.yyy.yyy.yyy。 您可以尝试将logging.properties中的org.apache.catalina.valves.RemoteIpValve.level的日志级别提高到FINE 【参考方案1】:

改变 AccessLogValve 的模式是我的解决方案,就像这样:

<Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
prefix="localhost_access_log" suffix=".txt"
pattern="%x-forwarded-fori %l %u %t &quot;%r&quot; %s %b" />

来源:https://***.com/a/36357291/1830268

完整的模式属性选项在这里:https://tomcat.apache.org/tomcat-9.0-doc/config/valve.html#Access_Log_Valve/Attributes

【讨论】:

不幸的是,这是一个半解决方案:OP 试图实现的目标不仅限于漂亮的日志。 ServletRequest#getRemoteAddr 必须返回真实客户端的 IP,以便 RemoteAddrValve 等其他重要阀门正常工作。如果RemoteIpValve 工作正常,则问题中的模式也必须工作。 就我而言,据我了解 OP 的问题,RemoteIpValve 工作正常,即调用 getRemoteAddress 正确报告了真实的远程 IP,但 accessLog 模式中的 %h 属性仍然返回代理IP 而不是远程客户端 IP。在我的情况下,用 %x-forwarded-fori 更改 %h 修复了访问日志中记录的 IP。我理解 OP 问题的方式与我的问题相同。 AccessLogValveRemoteIpValve 前后更改远程地址后调用返回。这就是为什么%h 不起作用的原因除非您还使用requestAttributesEnabled="true"(就像OP 所做的那样),在这种情况下,远程地址取自请求属性(准确地说是org.apache.catalina.AccessLog.RemoteAddr)而不是请求自己。 谢谢,我错过了 requestAttributesEnabled 选项,这对我的情况很有帮助。

以上是关于Tomcat:“X-Forwarded-For”不适用于负载均衡器的主要内容,如果未能解决你的问题,请参考以下文章

阿里云X-Forwarded-For 发现tomcat记录的日志所有来自于SLB转发的IP地址,不能获取到请求的真实IP。

Tomcat中获取客户端真实IP及协议

X-Forwarded-For的一些理解

X-Forwarded-For的一些理解

tomcat获取访问者真实IP

tomcat 修改日志路径以及优化内存和启动速度