如何在tomcat访问日志中记录客户端IP和X-Forwarded-For IP

9

如何在Tomcat访问日志中记录客户端IP和X-Forwarded-For IP。

我正在使用% {X-Forwarded-For}i,如果通过负载均衡器访问,则记录实际客户端地址。但是,如果我直接访问Tomcat实例,则不记录实际客户端地址。是否有一种方法可以在这两种情况下显示实际客户端IP地址?

4个回答

14

来自http://www.techstacks.com/howto/configure-access-logging-in-tomcat.html

如果你正在运行的Tomcat版本大于6.0.21或Tomcat 7,你可以利用新的Remote IP Valve。对于访问日志记录,这个valve的好处是,如果X-Forwarded-For头传递了IP地址,它将自动将客户端IP与传递的IP地址交换。加载它非常容易。只需在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>

如果你正在使用早于6.0.21的tomcat 6版本,并希望存储X-Forwarded-For IP地址,那么你可以修改AccessLogValve的pattern属性。你需要删除“常规”或“综合”模式,并将其替换为以下其中一种模式:
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 地址。你仍然会记录请求,但不知道它来自哪里。


这在通过负载均衡器时有效,但是在直接访问Tomcat实例跳过负载均衡器URL时不记录IP地址。有没有办法在两种情况下都记录IP地址? - Kishore Tamire
2
您还需要在AccessLogValue中将requestAttributesEnabled属性设置为true - sandeepd

4

我曾经遇到过使用Apache反向代理在Tomcat/9.0.12上运行Java应用程序时出现的问题。

我通过将以下内容添加到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,因为这些是默认值,但我为了清晰起见添加了它们。%a将显示代理IP(或负载均衡器),而%{x-forwarded-for}i将显示用户IP。有关更多详细信息,请参阅以下链接:https://tomcat.apache.org/tomcat-9.0-doc/api/org/apache/catalina/valves/RemoteIpValve.html。请注意,HTML标记已被保留。

1
x-forwarded-for 区分大小写吗? - Yu Jiaao
1
@YuJiaao HTTP头部不区分大小写。 - asgs

1
<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地址放入“org.apache.tomcat.remoteAddr”请求属性中。
AccessLogValve配置仅记录包含正确远程IP的“org.apache.tomcat.remoteAddr”请求属性。

它们都支持Valve定义。如果您需要为在Tomcat上运行的所有应用程序执行此操作,则需要在server.xml中执行。 - Mehmet Sunkur

0

为了进一步增加已经在这里提供的答案,您还可以排除负载均衡器记录检查。

当请求通过RemoteIpValve时,如果请求具有X-Forwarded-For头(或您配置的任何remoteIpHeader),则会向请求添加一个名为org.apache.catalina.AccessLog.RemoteAddr的属性。然后,您可以在AccessLogValve中仅在存在此属性时才记录它。

此示例适用于tomcat9。

<Valve className="org.apache.catalina.valves.RemoteIpValve" />

<Valve className="org.apache.catalina.valves.AccessLogValve"
    directory="logs"
    prefix="access"
    suffix=".log"
    pattern="combined"
    renameOnRotate="true"
    requestAttributesEnabled="true"
    maxDays="90"
    conditionIf="org.apache.catalina.AccessLog.RemoteAddr"
/>

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接