多级代理导致后端服务获取客户端信息有误

多级代理导致后端服务获取客户端信息有误 #

问题描述 #

经过多级代理、负载均衡,后端服务获取客户端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正则。
2023年12月6日