在宝塔面板进行反向代理时遇到一个蹊跷的现象:
- 后端地址使用http协议时访问站点正常,但由于要代理的站点有部分地址会根据访问协议自动跳转到https访问,导致循环跳转而不能正常访问;
- 后端地址必须使用https协议才能正常访问,但更换后直接显示 502 Bad Gateway;
- 后端地址换成WAF地址,再由WAF反代到目标地址能够正常访问。
由此得出结论,肯定是有某种神秘力量在干预反向代理正常工作。在进行排查时发现,被代理的站点服务器不能通过IP直接访问(部分IDC防止直接通过IP访问被滥用而拦截)。在反代时已经添加了Host头部信息,而且尝试通过WAF反代是能正常访问的,在问题解决前一直认为通过IP访问拦截应该不是反代显示502的原因。

想到通过HTTPS协议访问时,通常情况下服务器需要通过SNI(全称Server Name Indication,中文意思是服务器名称指示)进行识别,否则服务器则会通过默认的SSL证书进行TLS握手访问默认站点,该默认站点正是通过IP访问的站点。
在宝塔面板设置反代时后端地址使用HTTPS协议,查看Nginx反代部分的配置代码发现并没有发送SNI相关的代码,在默认情况下后端服务器会先进行TLS握手,然后才获取到请求的HOST头。这种情况下,后端服务器会使用默认的SSL证书进行TLS握手,而不会根据请求的域名选择对应的SSL证书。
由于IDC已禁用了IP访问,在TLS握手阶段由于没有包含SNI信息,被IDC视为通过IP访问,还没有到后端服务器尝试通过默认SSL证书握手阶段就被阻断,导致反代后访问显示 502 Bad Gateway 的情况。
为了解决该问题,需要在设置反代时正确发送SNI到后端,添加如下代码即可:
proxy_ssl_server_name on;
proxy_ssl_name www.jiangdefu.com;