腾讯 CLB下多级 Nginx 服务直接出现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,但是 naco s配置文件写死 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\"}"; } |