Why Nginx Reverse Proxy Fails with HTTPS and How to Fix SSL SNI Errors
This article walks through a real‑world Nginx reverse‑proxy SSL issue, explains the root cause of 502 and handshake failures caused by missing SNI support, and provides step‑by‑step configuration changes and code snippets to resolve the problem.
1. Phenomenon
When using Nginx as a reverse proxy for a backend server identified by a domain name, HTTPS requests fail, producing SSL errors and a JavaScript 502 response.
2. Investigation Process
1) Nginx logs show a 502 error, but a direct curl to the upstream domain works.
2) The backend server receives no request, indicating the request never reaches it. The Nginx configuration was checked; HTTPS rendering works, but using the upstream still fails.
3) Switching to an internal IP (bypassing the domain) works, confirming the issue is domain‑related.
4) The Nginx error log reveals an unreadable error line: the domain was resolved to an IP, and a direct IP request fails.
The problem is identified as an SNI (Server Name Indication) issue; Nginx must send the original domain name when proxying HTTPS.
3. Solution
Nginx provides the
proxy_ssl_server_namedirective to enable SNI.
Without using
upstream, add the following to the server block:
<code>proxy_ssl_server_name on;</code>If you still want to use
upstreamfor load balancing, the following configuration works:
<code>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;
}
</code>After applying the configuration, the issue is resolved.
4. Root Cause Analysis
The error log shows a handshake failure:
<code>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/..."</code>In a local environment the domain works, but through Nginx the DNS resolves to an IP. The same public IP hosts multiple services distinguished by
server_name. Without SNI, the backend cannot route the request correctly.
Successful request methods:
Direct domain request.
IP request with the correct
Hostheader (enabled by
proxy_ssl_server_name on;and related header settings).
Key directives to add:
proxy_ssl_server_name on; proxy_ssl_name 域名; proxy_set_header Host 域名;Additional notes:
Multiple domains can share a public IP; Nginx uses
server_nameto differentiate.
When compiling Nginx for HTTPS reverse proxy, include
--with-http_ssl_module.
Alibaba Cloud SLB can terminate SSL at layer 7.
Variable
Shows Port?
Value Exists?
host
No
"Host:value" shows only the hostname part.
http_host
Yes
Displays the full Host header when present.
proxy_host
Defaults to 80, other ports not shown
"Host:value" is displayed.
References:
https://www.cnblogs.com/faberbeta/p/nginx012.html
https://blog.dianduidian.com/post/nginx反向代理当后端为https时的一些细节和原理/
Ops Development Stories
Maintained by a like‑minded team, covering both operations and development. Topics span Linux ops, DevOps toolchain, Kubernetes containerization, monitoring, log collection, network security, and Python or Go development. Team members: Qiao Ke, wanger, Dong Ge, Su Xin, Hua Zai, Zheng Ge, Teacher Xia.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.