Node.js 如何从haproxy docker容器中的请求获取客户端IP?

Node.js 如何从haproxy docker容器中的请求获取客户端IP?,node.js,networking,docker,haproxy,Node.js,Networking,Docker,Haproxy,我正试图从nodejs服务器中的请求对象获取客户端的IP地址 我的技术结构是: 我运行两个docker容器。一个用于haproxy,另一个用于使用expressjs框架的nodejs。所有传入流量首先由haproxy接收,我使用它进行代理和负载平衡。Haproxy根据配置文件中的ACL将请求转发到适当的后端 我尝试访问节点内的x-forwarded-for请求头,但它只返回docker网络网关接口的IP172.17.0.1 转到haproxy配置,并在defaults块中使用头X-Client-

我正试图从nodejs服务器中的请求对象获取客户端的IP地址

我的技术结构是: 我运行两个docker容器。一个用于
haproxy
,另一个用于使用
expressjs
框架的
nodejs
。所有传入流量首先由haproxy接收,我使用它进行代理和负载平衡。Haproxy根据配置文件中的
ACL
将请求转发到适当的后端

我尝试访问节点内的
x-forwarded-for
请求头,但它只返回docker网络网关接口的IP
172.17.0.1

转到
haproxy
配置,并在
defaults
块中使用头X-Client-IP的
选项forward,还将
X-Client-IP
头设置为docker网络网关接口IP。调试日志也记录相同的ip

这就是问题所在。由于
haproxy
在容器内运行,它认为docker网络网关接口就是客户端

如何将实际客户端的IP发送到容器内的haproxy,以便它可以转发到nodejs

这是我的
haproxy
配置文件:

global
    debug
    maxconn 4096

defaults
    mode http
    timeout connect 5000ms
    timeout client 50000ms
    timeout server 50000ms
    timeout http-keep-alive 50000ms
    option http-keep-alive
    option http-server-close
    option forwardfor header X-Client-IP

frontend http-in
    bind *:80
    acl is_api hdr_end(host) -i api.3dphy-dev.com

    use_backend api if is_api

    default_backend default

backend default
    server s0 "${DOCKER_INTERFACE_IP}:3000"

backend api
    balance leastconn
    option httpclose
    option forwardfor
    server s1 "${DOCKER_INTERFACE_IP}:17884"
我使用以下方法运行haproxy容器:

docker run -d --name haproxy_1 -p 80:80 -e DOCKER_INTERFACE_IP=`ifconfig docker0 | grep -oP 'inet addr:\K\S+'` -v $(pwd)/config/haproxy.cfg:/usr/local/etc/haproxy/haproxy.cfg:ro haproxy:1.6

注意:我没有使用任何防火墙。另外,请随时建议对我的配置进行任何改进。保持活动状态也是一个问题。

haproxy的工作方式是不可能的,因为当您在启动时不连接主机时,它会不断抛出,因为它需要完全解析地址。我已经尝试了很多解决方法(也许是可能的),但我放弃了,用
docker compose

我在前面的一篇文章中发布了一个运行示例,可能会有所帮助

要点是将容器与实际上已经存在的主机链接。这是由docker链接完成的

docker-compose.yml

haproxy.cfg


在浏览了docker论坛后,终于找到了解决方案

解决方案分为两步

首先,我需要将我的
haproxy
配置更新为:

global
    debug
    maxconn 4096

defaults
    mode http
    timeout connect 5000ms
    timeout client 50000ms
    timeout server 50000ms
    timeout http-keep-alive 50000ms
    option http-keep-alive
    option http-server-close

frontend http-in
    bind *:80
    option forwardfor
    acl is_site hdr_end(host) -i surenderthakran-dev.com

    use_backend site if is_site

    default_backend default

backend default
    server s0 "${DOCKER_INTERFACE_IP}:3000"

backend site
    balance leastconn
    option httpclose
    option forwardfor
    server s1 "${DOCKER_INTERFACE_IP}:17884"
请注意,在
前端http in
块中添加了
选项forwardfor
。这告诉haproxy的前端部分将客户端IP添加到请求头中

其次,docker run命令应更新为:

docker run -d --name haproxy_1 -p 80:80 -e DOCKER_INTERFACE_IP=`ifconfig docker0 | grep -oP 'inet addr:\K\S+'` -v $(pwd)/config/haproxy.cfg:/usr/local/etc/haproxy/haproxy.cfg:ro --net=host haproxy:1.6
注意在docker run命令中添加了
--net=host
选项。它告诉docker启动新容器并使用与主机相同的网卡


现在,原始客户端IP被添加到请求头中,并且可以在请求转发到的任何应用程序的
x-forwarded-for
请求头中访问该IP。

。我看到了恐怖。。。。见下面的答案。我也有一个正常工作的haproxy:1.6版本,但这不是问题所在。谢谢你的解决方案。请注意,如果使用主机网络,则不需要-p80:80选项。根据使用主机模式联网时。。。而-p。。。被忽略,而是产生一个警告:另外,如果使用docker服务--net=host应该替换为--network host
global
    debug
    maxconn 4096

defaults
    mode http
    timeout connect 5000ms
    timeout client 50000ms
    timeout server 50000ms
    timeout http-keep-alive 50000ms
    option http-keep-alive
    option http-server-close

frontend http-in
    bind *:80
    option forwardfor
    acl is_site hdr_end(host) -i surenderthakran-dev.com

    use_backend site if is_site

    default_backend default

backend default
    server s0 "${DOCKER_INTERFACE_IP}:3000"

backend site
    balance leastconn
    option httpclose
    option forwardfor
    server s1 "${DOCKER_INTERFACE_IP}:17884"
docker run -d --name haproxy_1 -p 80:80 -e DOCKER_INTERFACE_IP=`ifconfig docker0 | grep -oP 'inet addr:\K\S+'` -v $(pwd)/config/haproxy.cfg:/usr/local/etc/haproxy/haproxy.cfg:ro --net=host haproxy:1.6