【发布时间】:2018-06-14 16:19:00
【问题描述】:
如何在 tomcat 访问日志中记录客户端 IP 和 X-Forwarded-For IP。
我正在使用 %{X-Forwarded-For}i,如果我通过负载均衡器访问,它会记录实际的客户端地址。但如果我直接访问 tomcat 实例,则不会记录实际的客户端地址。有没有办法在这两种情况下显示实际的客户端 IP 地址?
【问题讨论】:
标签: java tomcat http-headers ip load-balancing
如何在 tomcat 访问日志中记录客户端 IP 和 X-Forwarded-For IP。
我正在使用 %{X-Forwarded-For}i,如果我通过负载均衡器访问,它会记录实际的客户端地址。但如果我直接访问 tomcat 实例,则不会记录实际的客户端地址。有没有办法在这两种情况下显示实际的客户端 IP 地址?
【问题讨论】:
标签: java tomcat http-headers ip load-balancing
来自http://www.techstacks.com/howto/configure-access-logging-in-tomcat.html:
如果您运行的 tomcat 版本高于 6.0.21 或 tomcat 7,则可以利用新的远程 IP 阀。对于访问日志记录,这个 Valve 的好处是它会自动交换客户端 IP 与通过 X-Forwarded-For 标头传递的 IP 地址,如果 IP 地址在 X-Forwarded-For 标头中传递。加载它非常容易。只需在 AccessLogValve 声明之前将 org.apache.catalina.valves.RemoteIpValve 添加到 server.xml 中。例如:
<Host name="localhost" appBase="webapps" unpackWARs="true" autoDeploy="true" xmlValidation="false" xmlNamespaceAware="false">
<!-- Remote IP Valve -->
<Valve className="org.apache.catalina.valves.RemoteIpValve" />
<!-- Access log processes all example.
Documentation at: /docs/config/valve.html -->
<Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
prefix="localhost_access_log." suffix=".txt"
pattern="combined" resolveHosts="false"/>
-->
</Host>
如果您使用的 tomcat 6 版本早于 6.0.21,并且您想存储 X-Forwarded-For IP 地址,那么您可以修改 AccessLogValve 的模式属性。您需要删除“通用”或“组合”模式并将其替换为以下模式之一:
Common Log Format: %{X-Forwarded-For}i %l %u %t "%r" %s %b
Combined Log Format: %{X-Forwarded-For}i %l %u %t %r %s %b %{User-Agent}i %{Referer}i
RemoteIP Valve 解决的主要问题是,您只能在日志中获得 X-Forwarded-For 地址。如果您直接访问应用服务器,绕过在请求中插入 X-Forwarded-For 标头的设备,您将不会记录 IP 地址。你仍然会记录一个请求——你只是不知道它来自哪里。
【讨论】:
requestAttributesEnabled 属性设置为true。
我在 Tomcat/9.0.12 上运行的 Java 应用程序前面使用 Apache 反向代理时遇到了这个问题
我通过将它添加到 Tomcat conf/server.xml 来修复它,放置阀门的位置将取决于您希望在每个引擎/主机/上下文中应用它的天气,我已经添加了这 2 个阀门
<Valve className="org.apache.catalina.valves.RemoteIpValve" remoteIpHeader="x-forwarded-for" protocolHeader="x-forwarded-proto" />
<Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs" prefix="tomcat_access_log" suffix=".log" pattern="%t %{X-AUSERNAME}o %{User-Agent}i %a %m %r %b %s %D %I %{x-forwarded-for}i" />
您不需要定义所有 remoteIpHeader 和 protocolHeader 因为它们是默认值,但我添加它们只是为了清楚起见https://tomcat.apache.org/tomcat-9.0-doc/api/org/apache/catalina/valves/RemoteIpValve.html
%a 将显示代理 ip(或负载均衡器),%{x-forwarded-for}i 将显示用户 ip
【讨论】:
x-forwarded-for 是否区分大小写?
<Valve className="org.apache.catalina.valves.RemoteIpValve"
remoteIpHeader="x-forwarded-for" />
<Valve className="org.apache.catalina.valves.AccessLogValve"
requestAttributesEnabled="true"
pattern="Remote Ip is: %{org.apache.tomcat.remoteAddr}r" />
您可以将这两个 Valve 定义添加到 context.xml 中。所以你可以在这两种情况下看到远程 ip。通过负载均衡器或直接。
org.apache.catalina.valves.RemoteIpValve 检测到“x-forwarded-for”标头。如果标头中有“x-forwarded-for”,则将其值放入“org.apache.tomcat.remoteAddr”请求属性中。如果标头中没有“x-forwarded-for”,则将客户端 ip addr 放入“org.apache.tomcat.remoteAddr”请求属性中。
AccessLogValve 配置只记录包含正确远程 IP 的“org.apache.tomcat.remoteAddr”请求属性。
【讨论】: