多级代理导致后端服务获取客户端信息有误 #
问题描述 #
经过多级代理、负载均衡,后端服务获取客户端IP、获取请求协议、获取请求端口、重定向,得到错误结果。
解决方式 #
步骤 1 (一级代理) #
若是云服务(如阿里云ALB负载均衡),配置里勾选请求头部,如下:
plaintext
X-Forwarded-For 客户端IP地址
X-Forwarded-Proto 请求协议(http、https)
X-Forwarded-Port 请求端口号
若是nginx,配置如下:
plaintext
proxy_set_header Host $host;
#proxy_set_header X-Real-IP $remote_addr; # 可选
proxy_set_header X-Forwarded-For $remote_addr; # 也可以使用 $proxy_add_x_forwarded_for
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Port $server_port;
步骤 2 (二级或二级以上代理) #
后端nginx配置,如下:
plaintext
# 配置真实IP头部
real_ip_header X-Forwarded-For; # 真实IP所在头部。Nginx会将获取到的真实IP赋值给变量 $remote_addr 。
real_ip_recursive on; # 启用后,将会将以下IP视为授信代理,只有TCP连接远程IP属于授信代理时,才会使用realip模块获取真实IP。
set_real_ip_from 100.127.0.0/16;
#set_real_ip_from 100.120.170.0/25;
#set_real_ip_from 100.120.170.128/25;
#set_real_ip_from 100.120.171.0/25;
#set_real_ip_from 100.120.171.128/25;
#set_real_ip_from 100.121.119.128/25;
#set_real_ip_from 100.121.120.0/25;
#set_real_ip_from 100.121.120.128/25;
#set_real_ip_from 100.121.121.0/25;
# 配置转发头部
#proxy_set_header X-Real-IP $remote_addr; # 可选
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $http_x_forwarded_proto;
proxy_set_header X-Forwarded-Port $http_x_forwarded_port;
相关指令语法:
plaintext
https://nginx.org/en/docs/http/ngx_http_realip_module.html
Syntax: real_ip_header field | X-Real-IP | X-Forwarded-For | proxy_protocol;
Default: real_ip_header X-Real-IP;
Context: http, server, location
Syntax: set_real_ip_from address | CIDR | unix:;
Default: --
Context: http, server, location
Syntax: real_ip_recursive on | off;
Default: real_ip_recursive off;
Context: http, server, location
https://nginx.org/en/docs/http/ngx_http_proxy_module.html
$proxy_add_x_forwarded_for:
The “X-Forwarded-For” client request header field with the $remote_addr variable appended to it, separated by a comma. If the “X-Forwarded-For” field is not present in the client request header, the $proxy_add_x_forwarded_for variable is equal to the $remote_addr variable.
步骤 3 #
若是后端服务是SpringBoot,详见相关Issue:
HTTPS代理转发到HTTP后端服务SpringBoot导致协议获取有误
若后端服务是Tomcat,则配置 settings.xml,如下:
xml
<!-- Engine 域 或者 Host 域 -->
<Valve className="org.apache.catalina.valves.RemoteIpValve"
remoteIpHeader="X-Forwarded-For"
protocolHeader="X-Forwarded-Proto"
protocolHeaderHttpsValue="https"
portHeader="X-Forwarded-Port"
internalProxies="10\.\d{1,3}\.\d{1,3}\.\d{1,3}|192\.168\.\d{1,3}\.\d{1,3}|169\.254\.\d{1,3}\.\d{1,3}|127\.\d{1,3}\.\d{1,3}\.\d{1,3}|172\.1[6-9]{1}\.\d{1,3}\.\d{1,3}|172\.2[0-9]{1}\.\d{1,3}\.\d{1,3}|172\.3[0-1]{1}\.\d{1,3}\.\d{1,3}"
/>
- 在 internalProxies 属性中添加上级直连代理的IP正则。