haproxy 并将客户端 IP 地址转发到服务器

haproxy 并将客户端 IP 地址转发到服务器

我对 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_FORx-forwarded-for可能与HAproxy版本有关,因为答案是5年前写的……?

举个例子,这是在生产过程中发生的:

String requestIp = httpRequest.getHeader("x-forwarded-for");

相关内容