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


15

我的HAproxy有问题。

我使用HAproxy作为负载平衡器,它将传入的HTTP请求分发到5个Web服务器。通常,使用负载均衡器的IP将客户请求转发到Web服务器。但是我需要从Web服务器请求某些内容的客户端IP或真实IP。因为我们需要记录真实客户端的IP。

我尝试在Web服务器上获取客户端的IP,但是到目前为止我还无法成功。我总是看到负载均衡器的IP。

我使用x-forward-for选项,但无法解决问题。之后,我找到了另一个选项“ source 0.0.0.0:80 usesrc clientip ”,但是在尝试运行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?


您正在寻找的被称为“透明代理”。iptables以某种方式参与其中,但我不确定到底是如何进行的。
sysadmin1138

通过说透明代理,我提到,代理在分发传入连接时不会修改http标头。从而可以将真实的网页请求者客户端的IP发送到Web服务器。这就是我从透明代理中了解的内容。
系统

Answers:


15

我解决了这个问题。也许从一开始就不是问题。遇到此问题时,我进行了Google搜索,结果发现

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选项,但仍为我提供了loadbalancer的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 conf,以将X-forwarded-for记录在原源中(5h)

#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

感谢您的回答Marcelo,但在Apache日志中我们不需要客户端的IP地址。我们尝试通过我们的PHP脚本学习。
系统

1

刚刚尝试了@System的解决方案,似乎标题名称已从更改HTTP_X_FORWARDED_FORx-forwarded-for。可能与HAproxy版本有关,因为答案是5年前写的...?

例如,这正在生产中:

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

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.