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