在 HAProxy 中传递客户端真实 IP,核心是在配置文件中启用 option forwardfor 参数,并确保后端 Web 服务器(如 Nginx 或 Apache)配置为信任并解析该头部,否则后端只能看到负载均衡器的 IP。
先说结论:HAProxy 需开启 option forwardfor,后端需配置信任该头部来源,且不可无条件信任 X-Forwarded-For 以防伪造。
- 适合:HAProxy 作为七层负载均衡反向代理的场景
- 先准备:确认 HAProxy 配置权限及后端 Web 服务器类型(Nginx/Apache)
- 验收:通过后端日志或应用代码获取到的 IP 是否为客户端公网 IP
完整配置示例
在 HAProxy 配置的 listen 或 backend 模块下,添加以下参数即可开启透传。以下是完整的 backend 配置块示例,可直接复用:
backend web_servers
balance roundrobin
option forwardfor
option http-server-close
http-request set-header X-Real-IP %[src]
server web1 192.168.1.10:80 check
server web2 192.168.1.11:80 check若需自定义头部名称,可指定 header 参数:
option forwardfor header X-Real-IP注意:建议配合 option http-server-close 使用以确保连接正确处理,option httpclose 在较新版本中已不推荐。
后端服务器配置
1. 配置后端 Nginx
在后端 Nginx 配置中,必须声明信任 HAProxy 的 IP 段,并指定解析头部:
set_real_ip_from 192.168.1.0/24; # HAProxy 的 IP 段
real_ip_header X-Forwarded-For;
real_ip_recursive on;2. 配置后端 Apache
仅修改日志格式无法让应用逻辑获取真实 IP,需安装并配置 mod_remoteip 模块以替换 REMOTE_ADDR:
# 启用模块(Debian/Ubuntu)
a2enmod remoteip
# 配置文件 httpd.conf 或 sites-available 配置
RemoteIPHeader X-Forwarded-For
RemoteIPInternalProxy 192.168.1.0/24
RemoteIPInternalProxy 10.0.0.0/8配置完成后重启 Apache,应用层获取的 REMOTE_ADDR 即为真实客户端 IP。
curl 验证测试
使用 curl 命令发送请求并查看 verbose 输出,确认头部是否生成:
curl -v http://your-domain.com/在后端服务器抓包或查看访问日志,确认 X-Forwarded-For 字段存在且包含客户端公网 IP。例如 Nginx 日志格式配置:
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';后端应用代码获取示例
配置完成后,不同语言获取真实 IP 的方式如下:
PHP:
// 配置 mod_remoteip 后,直接使用
$ip = $_SERVER['REMOTE_ADDR'];
// 或未配置模块时手动获取
// $ip = $_SERVER['HTTP_X_FORWARDED_FOR'];Python (Flask):
from flask import request
# 需配置 ProxyFix 或信任代理
app.wsgi_app = ProxyFix(app.wsgi_app, x_for=1)
ip = request.remote_addrJava (Spring):
String ip = request.getHeader("X-Forwarded-For");
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getRemoteAddr();
}常见坑与风险
1. 安全信任问题:X-Forwarded-For 可被客户端伪造,后端必须仅信任来自 HAProxy 等可控代理的请求,不可直接采信公网请求中的该头部。
2. 多级代理链:若中间还有其他代理,X-Forwarded-For 会是 IP 链(如 client, proxy1, proxy2),后端需配置 recursive 模式或取第一个 IP,注意 HAProxy 默认是追加而非覆盖。
3. 连接模式影响:HAProxy 工作在隧道模式时可能仅对连接的第一个请求附加头部,需确保配置了 option http-server-close 以保证每个请求都处理。