我对 HAproxy 有一个问题。
我使用 HAproxy 作为负载均衡器,它将传入的 http 请求分发到 5 个 Web 服务器。通常,客户端请求会转发到具有负载均衡器 IP 的 Web 服务器。但我需要客户端 IP 或向 Web 服务器请求某些内容的真实 IP。因为我们需要记录真实客户端的 IP。
我尝试在 Web 服务器上获取客户端的 IP,但到目前为止无法成功。我总是看到负载均衡器的 IP。
我使用了 x-forward-for 选项,但问题没有解决。之后我找到了另一个选项“源 0.0.0.0:80 使用 rc 客户端 ip“但是我在尝试运行 HAproxy 时遇到了错误,这是关于使用 HAproxy 的 USE_TPROXY 选项进行编译的需求。我做到了,我使用 USE_TPROXY 选项重新编译了 HAproxy,但没有改变任何东西。我该怎么做才能了解真实客户端的 IP。
我的 Linux 内核版本是 2.6.32-34,意思是内核支持透明代理。我使用 UBUNTU 10.4 LTS
我的配置文件在这里
global
maxconn 100000
uid 99
gid 99
daemon
defaults
option forwardfor except 127.0.0.1
mode http
(1)source 0.0.0.0:80 interface hdr_ip(x-forwarded-for,-1)
(2)source 0.0.0.0:80 usesrc clientip
contimeout 5000
clitimeout 50000
srvtimeout 50000
listen myWeb 0.0.0.0:80
mode http
balance source
option forwardfor header X-Client
option http-server-close
stats enable
stats refresh 10s
stats hide-version
stats scope .
stats uri /lb?stats
stats realm LB2\ Statistics
stats auth admin:xXx
server S1 192.168.1.117:80 check inter 2000 fall 3
server S2 192.168.1.116:80 check inter 2000 fall 3
server S3 192.168.1.118:80 check inter 2000 fall 3
(1)(2)在测试 HAproxy 时我使用了以下两条线路中的一条。
有人可以帮我了解从我们的服务器请求的客户端的真实 IP 吗?
答案1
我解决了这个问题。也许从一开始就不是问题。当我遇到这个问题时,我进行了谷歌搜索,然后我看到
option forwardfor
行以便在 haproxy.cfg 文件中使用,还有其他选项。我尝试了这些选项,包括重新编译 haproxy... 但与了解 Web 服务器上真实客户端 IP 相关的真正问题并非源自 HAproxy,而是关于通过服务器脚本读取标头,在我们的例子中,这种脚本语言是 PHP。
我尝试通过这些命令来了解客户端的 IP
echo 'Client IP: '.$_SERVER["REMOTE_ADDR"];
echo 'Client IP: '.$_SERVER["HTTP_CLIENT_IP"];
这些命令显示负载均衡器的 IP。这是正确的,但这不是我期望的。尽管这些命令有 forwardfor 选项,但它们还是给出了负载均衡器的 IP
通过使用 forwardfor 选项,我们使 HAproxy 能够将 x-forwarded-for 标头插入到发送到我们 Web 服务器的客户端请求中。HAproxy 将此字段放入标头中,但我忽略了这一点。今天我意识到这是一个标头字段,我必须像这样读取此标头
echo 'Client IP: '.$_SERVER["HTTP_X_FORWARDED_FOR"];
通过此命令,我获得了客户端的 IP 地址而不是负载均衡器的 IP 地址。
但我的建议是,为了获取标题数据来调查其他信息,请使用 PHP 的 getallheaders() 函数。
//from php.net http://php.net/manual/en/function.getallheaders.php
foreach (getallheaders() as $name => $value) {
echo "$name: $value<br>\n";
}
我最后的 haproxy.cfg 文件的结尾如下所示。
global
maxconn 100000
uid 99
gid 99
daemon
defaults
option forwardfor except 127.0.0.1
mode http
contimeout 5000
clitimeout 50000
srvtimeout 50000
listen myWeb 0.0.0.0:80
mode http
balance source
option forwardfor
option http-server-close
stats enable
stats refresh 10s
stats hide-version
stats scope .
stats uri /lb?stats
stats realm LB2\ Statistics
stats auth admin:passwd
server S1 192.168.1.117:80 check inter 2000 fall 3
server S2 192.168.1.116:80 check inter 2000 fall 3
server S3 192.168.1.118:80 check inter 2000 fall 3
然而,我对 HAproxy 有很多不了解的地方,比如 uid 或 gid 的含义。
答案2
如果您需要 Apache 日志中的客户端 IP 地址,您可以更改 Apache 配置以记录 X-forwarded-for 来代替原始源(5 小时)
#LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
LogFormat "%{X-Forwarded-For}i %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
答案3
刚刚尝试了@System的解决方案,似乎标头名称已从更改为HTTP_X_FORWARDED_FOR
。x-forwarded-for
可能与HAproxy版本有关,因为答案是5年前写的……?
举个例子,这是在生产过程中发生的:
String requestIp = httpRequest.getHeader("x-forwarded-for");