在我的 HAProxy 负载均衡器中,我有以下配置块:
defaults
mode http
log global
option httplog clf
option dontlognull
option http-server-close
option forwardfor except 127.0.0.0/8
option redispatch
frontend main_http *:80
option forwardfor except 127.0.0.1
option httpclose
default_backend backend_http
backend backend_http
balance roundrobin
option httpchk
server node1 10.0.0.64:80 check port 80
server node2 10.0.0.65:80 check port 80
server node3 10.0.0.66:80 check port 80
在节点(Tomcat)上,我以这种格式记录请求(结合第一个字段中的 x-forwarded-for 和附加在末尾的实际 REMOTE_ADDR):
pattern='%{X-Forwarded-For}i - %u %t "%r" %s %b "%{Referer}i" "%{User-Agent}i" %a'
对于大多数请求来说,这似乎效果很好,但在某些情况下,我假设客户端本身位于代理后面,我看到请求的第一个字段包含这些值(每行代表一个真实请求,为了保护隐私,我破坏了真实 IP):
10.83.103.44, 10.83.103.44
10.83.198.52, 10.83.198.52
10.53.109.36, 10.53.109.36
unknown, unknown
192.168.1.43, 127.0.0.1
192.168.11.189, 127.0.0.1
10.1.6.3, 216.x.y.194, 10.37.52.202
192.168.50.250, 38.x.y.5, 10.37.31.201
根据 HAproxy 文档,最后一个 X-Forwarded-For 应该是它附加的正确 X-Forwarded-For,但事实似乎并非如此。我的应用程序使用客户端 IP 进行地理查找,因此这不仅仅是日志记录问题,它实际上把事情搞砸了。
我想做的是:不要让 HAproxy 将客户端的 IP 附加到它收到的现有 X-Forwarded-For 标头,而是直接覆盖它。因此,如果它X-Forwarded-For: 10.1.2.3
从 IP 地址 98.76.54.32 接收,它发送给客户端的只是X-Forwarded-For: 98.76.54.32
。有什么办法吗?我想知道为什么如此明显的垃圾信息会进入节点 -unknown, unknown
显然是垃圾信息 - 但如果存在解决方法,我会选择一种解决方法。
提前致谢。
答案1
在 HAProxy 添加自己的请求标头之前,将其从请求标头中撕下:
reqidel ^X-Forwarded-For:.*
此更改的风险是您将丢失有关“真实”客户端 IP 地址的信息 - 您的日志将显示客户端正在使用的代理服务器的 IP。听起来您对此没意见!
另外,参见这个问题有关标题附加顺序混淆的一些有趣信息X-Forwarded-For
。
答案2
如果您仍然感到困惑,可以直接使用以下两个代码片段之一:
第一的:
backend forward_real_ip
mode http
reqidel ^X-Forwarded-For:.*
option forwardfor
第二:
backend forward_real_ip
mode http
http-request set-header X-Forwarded-For %[src]
请参阅 HAProxy 文档:
答案3
如果您专门查看 haproxy 文档中的forwardedfor
选项,您可以阅读:
option forwardfor [ except <network> ] [ header <name> ] [ if-none ]
您可以在配置中更改相应的行,例如:
option forwardfor except 127.0.0.1 header My-X-Forwarded-For
这样,您最终会得到两个X-Forwarded-For
标头。这可能对您保持客户端真实 IP 有用,同时,您还可以让 haproxy 插入其标头而不会造成混淆。
这只是您可能感兴趣的另一个选择:)