负载均衡将https请求转发后端http服务报错:The plain HTTP request was sent to HTTPS port
https请求报错:The plain HTTP request was sent to HTTPS port
示例背景描述:
- www.test.com:11001服务需要对互联网使用https提供服务
- 后端java服务不支持https请求,且后端程序无法修改,仅支持http请求
问题描述:
- 因此在访问https://www.test.com:11001,URL会跳转http://www.test.com:11001,然后报错The plain HTTP request was sent to HTTPS port
报错如下:
解决思路:通过nginx代理
此处暂时将后端服务器设定为192.168.1.1,具体配置如下:
server {listen 11001;server_name localhost;location / {proxy_pass http://192.168.1.1:11001/;proxy_set_header Host $host:$server_port; # 包含端口号防止丢失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 https; # 强制设置协议为 HTTPSproxy_set_header X-Forwarded-Port $server_port; # 传递端口# 重定向修正proxy_redirect ~^(http://[^:/]+)(:([0-9]+))?/(.*)$ https://$host:$server_port/$4;proxy_redirect ~^(http://)([^/]+)/(.*)$ https://$host:$server_port/$3;# 可选:日志调试access_log /var/log/nginx/redirect_fix.log main;error_log /var/log/nginx/redirect_error.log debug;# 可选配置proxy_connect_timeout 60s;proxy_read_timeout 60s;}# 可选配置error_page 500 502 503 504 /50x.html;location = /50x.html {root html;}}
关键配置说明
1、proxy_redirect 正则表达式:
proxy_redirect ~^(http://[^:/]+)(:([0-9]+))?/(.*)$ https://$host:$server_port/$4;
- 匹配任何 HTTP 重定向:http://domain:port/path 或 http://domain/path
- 替换为:https://原始域名:11001/path
2、备用规则:
proxy_redirect ~^(http://)([^/]+)/(.*)$ https://$host:$server_port/$3;
- 匹配格式:http://anything/path
- 替换为:https://原始域名:11001/path
3、强制协议头部:
proxy_set_header X-Forwarded-Proto https;
- 即使后端服务不使用这个头部,也设置它以保持一致性
测试与验证方法
1、测试配置:
nginx -t
2、重载配置:
nginx -s reload
3、监控日志:
tail -f /var/log/nginx/access.log
tail -f /var/log/nginx/error.log
tail -f /var/log/nginx/redirect_fix.log
tail -f /var/log/nginx/redirect_error.log
4、重新访问测试
https://www.test.com:11001
常见问题排查表
问题现象 | 可能原因 | 解决方案 |
---|---|---|
重定向循环 | 后端服务也尝试重定向 | 检查后端响应是否已经是HTTPS |
端口号不正确 | 正则匹配失败 | 添加更通用的匹配规则 |
HTTPS证书错误 | 证书不匹配 | 检查SLB证书是否有效 |
404 错误 | 路径被修改 | 检查正则中的路径捕获组 如 $4 和 $3 |
如果上述配置仍有问题,使用这个更强大的版本:
proxy_redirect ~^http(://[^/]+)?(:\d+)?/(.*)$ https://$host:$server_port/$3;
proxy_redirect ~^http(://)([^/]+)/(.*)$ https://$host:$server_port/$3;
proxy_redirect default;
这个规则会:
- 匹配任何以 http 开头的重定向
- 替换为 https + 原始域名 + 11001端口
- 保留原始路径不变