腾讯CLB下多级nginx 反向代理302错误异常记录
前言
最近公司接了一些外包项目服务,某个登录服务在这边政务云网络下正常,但通过了腾讯CLB下,服务直接出现302无限跳转的问题,就对此异常做个笔记记录。
问题及原因分析
问题
问题是因为第一次上CLB服务进行代理,在多级Nginx代理中因协议不一致导致的HTTPS显示不正常,导致服务无法判断协议头出现异常重复请求。
原因分析
通常的架构是内部的nginx之间采用的是http进行通讯,clb入口配置https,二级以及以上的nginx则是配置http。通常的架构配置如下图:
因为CLB这边只是简单配置了https,因此只能通过下一个NGINX配置与日志进行排查。
首先查看配置与这边生产配置一致。
location /cas {
proxy_pass http://172.25.8.2:56781;
proxy_redirect off;
proxy_set_header Host $http_host;
proxy_set_header X-Forwarded-Scheme $scheme;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
但通过访问后,异常出现很多302跳转请求,如下图:
通过查看nginx1的日志,发现scheme请求过来的内容是http
,但是proto过来内容是https
。
{"@timestamp":"2024-12-24T13:26:17+08:00","host":"vendor-common-0","server_ip":"172.25.8.11","client_ip":"127.0.0.1","xff":"127.0.0.1","domain":"aaa.xxxx.com","url":"/server/static/element-icons-9c88a535.woff","referer":"https://aaa.xxxx.com/server/static/index-44df1e9b.css","args":"","upstreamtime":"","responsetime":"0.000","request_method":"GET","status":"200","size":"24820","request_body":"","request_length":"4613","protocol":"HTTP/1.1","upstreamhost":"","file_dir":"/AppHome/services/suliang/web/server//static/element-icons-9c88a535.woff","proto":"https","scheme":"http","http_user_agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:133.0) Gecko/20100101 Firefox/133.0"}
在反馈此问题给技术同事后,告知因为代码协议头都是写死通过X-Forwarded-Scheme
,但是nacos配置文件写死以https://xxxxx.com
域名,导致服务协议头前后一致。
那后面明白了,是因为服务获取的协议内容,与配置文件以https
协议不一致造成的。
总而言之,在进行多级代理的时候,在多级Nginx代理中因协议不一致导致的HTTPS显示不正常,导致服务无法判断协议头出现异常重复请求。
在多级Nginx代理中,一级代理配置为HTTPS,而二级及以上的代理配置为HTTP,可能导致请求头中的
X-Forwarded-Proto
未正确设置,使得后端服务无法正确识别请求的协议。
解决方案
方案1:强制设置X-Forwarded-Proto
为https
proxy_set_header X-Forwarded-Proto https;
方案2:通过X-Forwarded-Proto
传递协议,并动态设置
# 在每一层的Nginx中设置
set $newscheme http;
if ($http_x_forwarded_proto = 'https') {
set $newscheme https;
}
proxy_set_header X-Forwarded-Proto $newscheme;
方案3:直接使用$http_x_forwarded_proto
进行设置
# 在二级及以上的代理中设置
proxy_set_header X-Forwarded-Proto $http_x_forwarded_proto;
最终重新在Nginx1上设置配置后,正常访问:
location /cas {
proxy_pass http://172.25.8.2:56781;
proxy_redirect off;
proxy_set_header Host $http_host;
proxy_set_header X-Forwarded-Scheme $http_x_forwarded_proto;
proxy_set_header X-Forwarded-Proto $http_x_forwarded_proto;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
#return 200 "{\"scheme\":\"$http_X_Forwarded_Proto\"}";
}