如何配置NGINX负载均衡基于X-Forwarded-For头实现ip_hash(而非请求源IP)
当然可以实现!NGINX其实提供了很直接的方式来解决这个问题,完全不用改动上游反向代理的配置——刚好匹配你说的没法控制反向代理的情况。
一、NGINX的推荐实现方案(用realip模块)
首先要确认你的NGINX编译时包含了ngx_http_realip_module模块,大部分官方预编译包默认都带了,不确定的话可以在命令行跑nginx -V,看输出里有没有--with-http_realip_module就行。
接下来在你的NGINX配置里(http块或者对应的server块)添加以下配置:
# 先指定信任的反向代理IP/网段——只有这些IP发来的X-Forwarded-For头才会被我们采信 set_real_ip_from 192.168.1.100; # 替换成你的反向代理实际IP # 要是有多个反向代理,直接重复加就行,也支持网段格式 # set_real_ip_from 10.0.0.0/24; # 告诉NGINX用X-Forwarded-For头的值来替换默认的$remote_addr变量 real_ip_header X-Forwarded-For; # 可选但推荐:如果请求经过了多层代理,X-Forwarded-For里会有多个IP,开启这个参数会取最左边的真实客户端IP real_ip_recursive on;
然后在你的upstream负载均衡块里,正常用ip_hash就可以了:
upstream backend_servers { ip_hash; server backend1.example.com; server backend2.example.com; server backend3.example.com; }
原理很简单:配置realip模块后,NGINX会把原本是反向代理IP的$remote_addr替换成X-Forwarded-For里的真实客户端IP,这时候ip_hash自然就基于真实客户端IP做会话绑定了。
二、NGINX的变通方案(不用realip模块)
如果你的NGINX确实没装realip模块,也可以用hash指令直接指定基于$http_x_forwarded_for变量来做负载均衡:
upstream backend_servers { hash $http_x_forwarded_for consistent; server backend1.example.com; server backend2.example.com; server backend3.example.com; }
这里的consistent参数是可选的,开启后当你增减后端服务器时,只会影响极少数会话的绑定关系,能减少业务波动,非常推荐加上。不过要注意,如果X-Forwarded-For里有多个IP(比如经过多层代理),$http_x_forwarded_for会是整个IP字符串,可能导致hash值不准确,所以还是优先用realip模块的方案更稳妥。
三、Apache负载均衡的实现方式
要是你考虑换用Apache,它的mod_proxy_balancer也能轻松实现这个需求。首先确保你启用了mod_proxy、mod_proxy_balancer、mod_proxy_http这几个模块,然后配置如下:
<Proxy "balancer://backend_servers"> BalancerMember http://backend1.example.com BalancerMember http://backend2.example.com BalancerMember http://backend3.example.com # 基于X-Forwarded-For头的第一个IP做会话绑定(处理多层代理场景) ProxySet stickysession=expr:%{HTTP:X-Forwarded-For};expr=split(%{HTTP:X-Forwarded-For}, ',')[0] # 要是确定X-Forwarded-For里只有一个IP,也可以简化成: # ProxySet stickysession=expr:%{HTTP:X-Forwarded-For} </Proxy> # 最后在VirtualHost里配置转发规则 ProxyPass / balancer://backend_servers/ ProxyPassReverse / balancer://backend_servers/
Apache的stickysession支持用表达式自定义会话标识,这里我们直接提取X-Forwarded-For里的真实客户端IP,就能实现和NGINX一样的会话绑定效果。
小提醒
不管用哪种负载均衡器,一定要只信任可信的反向代理服务器发送的X-Forwarded-For头,避免被恶意伪造IP打乱负载均衡策略——这也是NGINX里要配置set_real_ip_from的核心原因,Apache也可以用mod_remoteip模块做类似的IP替换,原理和NGINX的realip模块一致。
备注:内容来源于stack exchange,提问作者madgangmixers

