企业代理后Nginx反向代理:proxy_pass为HTTPS时如何使用HTTP上游?
问题描述
我在企业代理后方搭建Nginx反向代理,企业代理地址为http://someproxy.company.com:3128,支持处理HTTP和HTTPS请求。
当前Nginx配置如下:
HTTP模块配置
upstream subdomain.external.com { server someproxy.company.com:3128; }
Server模块配置
server { listen 443 ssl; server_name reverse.company.com; ssl_certificate mycert.cer; ssl_certificate_key mykey.key; ssl_session_cache shared:SSL:10m; ssl_session_timeout 10m; proxy_ssl_server_name on; ssl_protocols TLSv1.2 TLSv1.3; location /target { proxy_pass http://subdomain.external.com/target; proxy_set_header X-Real-IP $remote_addr; } }
当proxy_pass目标为HTTP时,通过企业代理能正常工作。但改为https://subdomain.external.com/target后,Nginx尝试用HTTPS连接上游,出现错误日志:
[error] 6524#6288: *1 SSL_do_handshake() failed (SSL: error:1408F10B:SSL routines:ssl3_get_record:wrong version number) while SSL handshaking to upstream, client: CLIENT_IP_HERE, server: reverse.company.com, request: "GET /activation HTTP/1.1", upstream: "https://someproxy.company.com:3128/target", host: "reverse.company.com"
企业代理仅提供HTTP地址处理两种请求,尝试过在location /target中添加以下参数但未解决问题:
proxy_set_header Host $http_host; proxy_set_header X_FORWARDED_PROTO http; proxy_set_header X-Real-IP $remote_addr; proxy_ssl_verify off;
请问如何让Nginx在proxy_pass目标为HTTPS时,仍用HTTP连接上游企业代理?
解决方案
核心问题是:当proxy_pass改为https://开头时,Nginx会默认尝试和上游建立SSL连接,但企业代理仅支持HTTP协议,因此出现握手错误。解决思路是让Nginx用HTTP连接企业代理,同时告知代理需要转发到HTTPS目标地址。
方案一:无需额外模块的通用配置
调整location块配置,移除仅适用于SSL连接场景的proxy_ssl_server_name on,并修改proxy_pass和请求头:
server { listen 443 ssl; server_name reverse.company.com; ssl_certificate mycert.cer; ssl_certificate_key mykey.key; ssl_session_cache shared:SSL:10m; ssl_session_timeout 10m; ssl_protocols TLSv1.2 TLSv1.3; location /target { # proxy_pass 指向HTTP代理,路径中携带完整HTTPS目标地址 proxy_pass http://someproxy.company.com:3128/https://subdomain.external.com/target; # 设置目标HTTPS域名的Host头,确保后端服务正确识别请求 proxy_set_header Host subdomain.external.com; proxy_set_header X-Real-IP $remote_addr; # 强制关闭上游SSL握手,明确用HTTP连接代理 proxy_ssl off; } }
方案二:使用CONNECT方法(需额外模块)
如果你的Nginx编译了ngx_http_proxy_connect_module模块,可采用更标准的HTTP CONNECT方法代理HTTPS请求,这是代理转发HTTPS的规范方式:
server { listen 443 ssl; server_name reverse.company.com; ssl_certificate mycert.cer; ssl_certificate_key mykey.key; ssl_session_cache shared:SSL:10m; ssl_session_timeout 10m; ssl_protocols TLSv1.2 TLSv1.3; location /target { proxy_pass http://someproxy.company.com:3128; proxy_set_header Host subdomain.external.com; proxy_set_header X-Real-IP $remote_addr; # 启用CONNECT方法支持 proxy_connect; proxy_connect_allow 443; proxy_connect_connect_timeout 10s; proxy_connect_read_timeout 10s; proxy_connect_send_timeout 10s; } }
注意:官方默认编译的Nginx不包含
ngx_http_proxy_connect_module,需自行下载模块源码重新编译Nginx。
关键配置说明
proxy_ssl off:强制Nginx与上游代理使用HTTP连接,避免尝试SSL握手,直接解决报错根源proxy_set_header Host subdomain.external.com:让企业代理明确转发目标域名,确保后端HTTPS服务正确处理请求- 方案一中
proxy_pass路径包含完整HTTPS地址:让企业代理识别出这是需要转发到HTTPS的请求
内容的提问来源于stack exchange,提问作者AKzK
相关产品推荐
相关产品推荐

