nginx反向代理https域名时,请求报错502问题排查

微信公众号:运维开发故事,作者:冬子先生

一. 现象

在使用nginx反向代理后端服务器的时候,因为配置的是域名,导致HTTPS 请求转发失败,报 SSL 错误,js 报 502

图片

img

图片

img

二. 排查过程

1、查看nginx日志,发现报502,但是本地curl upstream中的后端域名是可以正常通的

图片

img

2、查看后端服务器上,没有收到请求,说明请求没过去,继续排查nginx本身的配置问题,Nginx 渲染模版已支持 HTTPS,尝试略过 upstream 配置,直接在 conf 文件中渲染 https://域名,请求仍然失败

3、然后换个思路,修改成内网ip不走域名,发现是正常,那换个域名试试

图片

img

图片

img

然后怀疑客户的域名有问题?但是这域名是可以访问的,上面第一步已经测试过了

4、这个时候只能翻一下错误日志,看看有什么有用的提示

图片

img

可以看到nginx错误日志里面有一串看不懂的报错提示和我们访问情况,nginx把域名解析成了一个ip地址,当我试着直接通过ip去访问时,果然报错了。

只能通过域名去访问,让我想起来了nginx同端口不同域名及禁用未绑定域名访问的配置,确实可以实现,这是https的SNI问题,大家可以自行查阅资料。

https://www.realks.com/2021/03/07/nginx-proxy-ssl-server-name/ https://freexyz.cn/server/98212.html

三. 解决方案

为解决这个问题,nginx官方给出了一个参数配置。

图片

img

然后我不使用 upstream了,而直接在 conf 文件中使用 https://域名 并且加上配置 proxy_ssl_server name_on;

图片

img

但是我如果还是想用upstream来负载均衡,有没有办法呢?一顿操作,发现可以像下面这样配置,也是可以正常访问的

location ^~ /modules/abm/ {
        proxy_ssl_server_name on;
        proxy_ssl_name 域名;
        proxy_set_header Host 域名;
        proxy_pass https://abtest_management_api_backend/modules/abm/;
        proxy_read_timeout 1800s;
        proxy_set_header Origanization-Id qiancheng;
        proxy_set_header X-Real-IP $clientRealIp;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_pass_header    X-Accel-Buffering;
    }

upstream abtest_management_api_backend {
        server 域名:443;

    }

问题解决,搞定!!

图片

img

四. 原因分析

仔细查看nginx error日志日志如下:

2023/07/07 00:03:56 [error] 29533#29533: *115403747 SSL_do_handshake() failed (SSL: error:14094410:SSL routines:ssl3_read_bytes:sslv3 alert handshake failure:SSL alert number 40) while SSL handshaking to upstream, client: 192.168.73.157, server: localhost, request: "HEAD /modules/abm/_sendata_ab_testing/nm_rc-virtual-list-_c6c90.73efda43.js HTTP/1.1", upstream: "https://114.80.1xxx1:443/modules/abm/_sendata_ab_testing/nm_rc-virtual-list-_c6c90.73efda43.js", host: "sc.xxx.com"

报错分析:在本地环境直接请求域名正常;但使用了nginx反向代理,在请求时DNS域名进行解析,真正请求出去的为IP与端口,但对方系统是多个域名对应一个公网ip,这个一个公网IP下映射到了多个项目和服务,通过nginx的server_name进行区分,故直接请求不通。

所以能成功请求方式有两种:

1、直接域名请求;

2、IP端口请求,但请求时需添加host;

即在nginx配置项中增加

proxy_ssl_server_name on;

或者设置请求头

proxy_ssl_server_name on;

proxy_ssl_name 域名;

proxy_set_header Host 域名;

(当你的nginx服务器作为反向代理,将client的请求转发到一个SSL服务器时,需要在HTTP请求头中包含SSL服务器的名称,这样SSL服务器才能正确地响应该请求。proxy_ssl_name指令就是设置proxy_pass指令所代理的SSL服务器的名称,即www.example.com。这样,在转发请求时,nginx就会在请求头中添加"Host: www.example.com"的参数,保证请求被正确地路由到目标SSL服务器。)

小知识:1.多个域名访问不同系统,使用同一个公网IP的情况;可以多个域名配置同一个公网IP和端口,映射到不同服务的nginx代理上,通过nginx配置server_name识别源域名,判定访问来源,进行请求处理。2.反向代理https请求,nginx编译安装时需要增加配置模块–with-http_ssl_module 3.使用阿里云的SLB作为负载均衡,证书可以配置在SLB上,但是要选择七层负载均衡。4.为啥添加host的时候只能写域名,不能通过变量获取。

proxy_set_header可以设置Host为、host与$http_host。

host的值设置为$proxy_host,是指nginx.conf的proxy_pass中设置的host值,也就是192.168.1.3,也就是服务器的IP地址。

不是一个固定的变量,他其实是http_HEADER通配后的结果。

http_content_type表示请求头里content-type属性的值,同理,$http_host指的就是请求头里的host属性。

$host是core模块内部的一个变量。

当请求头里不存在Host属性或者是个空值,$host则等于server_name

如果请求头里有Host属性,那么host就是www.example.com

变量是否显示端口值是否存在
host"Host:value"显示值为a:b的时候,只显示a
http_host“Host:value”,value存在就显示
proxy_host默认80不显示其他端口显示"Host:value"显示
  • 参考文档 https://www.cnblogs.com/faberbeta/p/nginx012.html https://blog.dianduidian.com/post/nginx反向代理当后端为https时的一些细节和原理/

公众号:运维开发故事

github:https://github.com/orgs/sunsharing-note/dashboard

博客**:https://www.devopstory.cn**

爱生活,爱运维

我是冬子先生,《运维开发故事》公众号团队中的一员,一线运维农民工,云原生实践者,这里不仅有硬核的技术干货,还有我们对技术的思考和感悟,欢迎关注我们的公众号,期待和你一起成长!

图片

### 宝塔面板 Nginx 反向代理配置教程最佳实践 #### 一、理解反向代理概念及其作用 反向代理是一种服务器端技术,通过设置特定规则使得客户端请求被透明转发到另一台或多台服务器上处理。对于Web应用而言,在宝塔面板中利用Nginx实现反向代理能够有效提升网站性能并简化访问流程。 #### 二、准备阶段——环境搭建与资源获取 确保已经成功安装Linux操作系统以及宝塔面板,并完成相应域名解析工作。如果计划部署Vue项目或其他前端框架,则需提前准备好待发布的静态文件或API接口地址[^5]。 #### 三、创建站点并开启SSL加密传输(可选) 登录至宝塔管理后台后新建一个虚拟主机条目用于承载目标服务;为了保障数据安全建议启用HTTPS协议支持,这一步骤可通过Let's Encrypt免费证书来达成自动化签发过程。 #### 四、编写具体的Nginx配置项 进入所建站名下的“配置文件编辑器”,依据实际需求调整如下参数: - **基础路径映射** ```nginx server { listen 80; server_name yourdomain.com; location /api/ { proxy_pass http://targetserver/api/; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header REMOTE-HOST $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } } ``` 上述示例展示了如何将`yourdomain.com/api/*`形式的HTTP GET/POST等操作重定向给远端名为`targetserver`的真实提供者负责响应。 - **WebSocket连接特殊处理** 当涉及到实通信场景比如在线聊天室等功能模块,还需额外指定一些头部字段以便维持持久化链路畅通无阻: ```nginx location /ws/ { proxy_pass https://websocket_server_address/; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; } ``` 此段落说明了针对WebSocket握手机制特有的指令集定义方式[^3]。 #### 五、保存修改后的设定并验证有效性 每次改动完毕之后都应当执行命令检验语法正确与否,防止因拼写错误等原因造成整个web service不可用的情况发生。具体做法是在SSH终端里输入以下语句来进行初步检测: ```bash /opt/nginx/sbin/nginx -t ``` 一旦确认无误即可正式生效新策略[^2]。 #### 六、常见问题排查指南 遇到诸如页面加载缓慢或是部分功能失效等问题,可以从以下几个方面入手分析原因所在: - 检查防火墙是否开放必要的TCP端口; - 查看日志记录寻找异常报错提示信息; - 对比源站返回状态码判断是否存在权限不足状况。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值