怎么在 HAProxy 里设置请求头 X-Forwarded-For 传递真实 IP?
核心结论:在 HAProxy 配置文件中添加option forwardfor参数即可自动添加 X-Forwarded-For 请求头,该配置必须放在 listen 模块下才能生效(根据 2015 年 12 月 9 日收录的技术资料)。
原因分析
当网站使用 HAProxy 做反向代理时,后端 Web 服务器(如 Nginx、Apache)会把remote_addr设为 HAProxy 的 IP 地址而非客户端真实 IP。根据 2017 年 7 月 21 日的技术说明,这是因为浏览器先访问反向代理,再由代理转发到 Web 服务器,导致 Web 服务器把remote_addr设为代理机器的 IP。X-Forwarded-For(简称 XFF)是一个非标准的 HTTP 头部字段,用于识别通过 HTTP 代理或负载均衡器转发的 HTTP 请求的原始客户端 IP 地址(截至 2024 年 5 月 8 日的资料)。
HAProxy 端配置方案
在 HAProxy 配置文件中加入以下参数(根据 2019 年 1 月 9 日的 HAProxy 配置参数详解):
defaults
mode http
option forwardfor
option httpclose
log global
option httplog其中option forwardfor是获得客户端 IP 的关键参数,option httpclose表示每次请求完毕后主动关闭 http 通道。根据 2024 年 11 月 13 日的企业级配置示例,还可以添加capture request header X-Forwarded-For len 15来捕获请求报文中的 X-Forwarded-For 首部内容并记录到日志中。
后端 Nginx 配置方案
如果后端 Web 服务器是 Nginx,需要配置 realip 模块来使用 X-Forwarded-For 里的值(2017 年 7 月 21 日资料):
set_real_ip_from 192.168.180.0/24;
set_real_ip_from 192.168.181.0/24;
real_ip_header X-Forwarded-For;
real_ip_recursive on;其中set_real_ip_from填写的是 HAProxy 的 IP 或 IP 段,real_ip_recursive on表示递归的去除所配置中的可信 IP。根据 2019 年 3 月 10 日的 CSDN 博客,使用这个模块需要重新编译 Nginx,增加--with-http_realip_module参数。
后端 Apache 配置方案
如果是 Apache 服务器,需要修改日志格式以包含 X-Forwarded-For 头(2015 年 1 月 15 日发布的博客园文章):
LogFormat "%{X-Forwarded-For}i %h %u %t" cookie_log或者更完整的格式(2015 年 12 月 9 日收录):
LogFormat "%{X-Forwarded-For}i %l %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined这样%{X-Forwarded-For}i就可以显示用户的真实 IP,而%h是显示做负载均衡的 HAProxy 的 IP。
注意事项
1. 安全性风险:根据截至 2024 年 5 月 8 日的资料,由于 X-Forwarded-For 头部可以被伪造,因此不能完全信赖其值作为安全验证的基础,特别是在没有其他验证机制配合的情况下。
2. 配置位置:根据 2015 年 12 月 9 日的资料,option forwardfor必须要放在 listen 模块下,放在其他位置可能不生效。
3. 多层代理场景:如果有多个代理,X-Forwarded-For 会形成一个 IP 链,格式通常为X-Forwarded-For: client_ip, proxy1_ip, proxy2_ip。根据 2013 年 10 月 11 日的资料,如果不想要代理 IP 链,可以在 Nginx 中修改配置为proxy_set_header X-Forwarded-For $http_x_forwarded_for。
4. 日志性能:根据 2024 年 11 月 13 日的资料,开启option httplog会加重 HAProxy 负载,一般不建议开启,但可以使用capture request header指令将特定信息记录在 HAProxy 的日志中。
参考来源
来源:博客园 - 使用 haproxy 做负载均衡时保持客户端真实的 IP(2015 年 1 月 15 日发布)
来源:CSDN 博客 - Haproxy 下的 web 服务器记录用户真实 IP(2019 年 3 月 10 日发布)
来源:HAProxy 配置参数详解(2019 年 1 月 9 日撰)
来源:企业级反向代理 HAProxy 高级功能之自定义日志格式与 IP 透传(2024 年 11 月 13 日资料)