最近在帮客户部署一个内部服务监控系统时遇到了一个典型场景:需要通过Nginx将HTTP请求代理到后端HTTPS服务,但该服务使用的是自签名证书。正常情况下,Nginx作为反向代理时会对后端服务的证书进行验证,这在生产环境中是必要的安全措施。但在开发测试环境或某些特殊场景下,我们可能需要临时跳过证书验证。
这种情况通常出现在:
重要提示:跳过证书验证会降低安全性,仅限在可控的内部网络或测试环境使用,生产环境必须配置完整的证书校验机制。
Nginx的标准HTTPS代理配置通常如下:
nginx复制location /api/ {
proxy_pass https://backend-service;
proxy_ssl_verify on;
proxy_ssl_verify_depth 2;
proxy_ssl_trusted_certificate /path/to/trusted_ca.crt;
}
这里有几个关键参数:
proxy_ssl_verify:控制是否验证后端证书(默认为on)proxy_ssl_verify_depth:设置证书链验证深度proxy_ssl_trusted_certificate:指定信任的CA证书路径当证书验证失败时,Nginx会返回502错误,并在错误日志中看到类似记录:
code复制[error] 1234#0: *1 SSL_do_handshake() failed
(SSL: error:1416F086:SSL routines:tls_process_server_certificate:
certificate verify failed) while SSL handshaking to upstream
要禁用证书验证,只需在location块中添加:
nginx复制location /api/ {
proxy_pass https://backend-service;
proxy_ssl_verify off;
}
这个简单的配置就能让Nginx跳过所有证书验证步骤。但实际生产中我们可能需要更精细的控制。
如果只想跳过主机名验证但仍验证证书有效性:
nginx复制proxy_ssl_verify on;
proxy_ssl_verify_depth 2;
proxy_ssl_server_name off;
可以指定特定的证书作为信任锚点:
nginx复制proxy_ssl_trusted_certificate /etc/nginx/conf.d/custom_ca.pem;
proxy_ssl_verify on;
对于需要SNI的场景:
nginx复制proxy_ssl_server_name on;
proxy_ssl_name $proxy_host;
nginx复制server {
listen 80;
server_name dev.example.com;
location / {
proxy_pass https://dev-backend:8443;
proxy_set_header Host $host;
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 $scheme;
# SSL配置
proxy_ssl_verify off;
proxy_ssl_session_reuse on;
}
}
nginx复制proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=api_cache:10m inactive=60m;
server {
listen 443 ssl;
server_name api.example.com;
ssl_certificate /etc/ssl/certs/api.example.com.crt;
ssl_certificate_key /etc/ssl/private/api.example.com.key;
location /external-api/ {
proxy_pass https://third-party-service.com/;
proxy_cache api_cache;
proxy_cache_valid 200 5m;
# 安全配置
proxy_ssl_verify off;
proxy_ssl_protocols TLSv1.2 TLSv1.3;
proxy_ssl_ciphers HIGH:!aNULL:!MD5;
# 超时控制
proxy_connect_timeout 10s;
proxy_read_timeout 30s;
}
}
忽略证书验证会带来以下风险:
如果可能,建议采用以下更安全的方案:
自签名CA方案:
证书固定方案:
nginx复制proxy_ssl_trusted_certificate /path/to/specific_cert.pem;
proxy_ssl_verify on;
短期证书方案:
即使在内网环境,也应建立监控机制:
proxy_ssl_verify off的使用情况启用会话复用可以提升性能:
nginx复制proxy_ssl_session_reuse on;
proxy_ssl_session_timeout 5m;
优化后端连接管理:
nginx复制upstream backend {
server backend1.example.com:443;
keepalive 32;
}
server {
location / {
proxy_pass https://backend;
proxy_http_version 1.1;
proxy_set_header Connection "";
}
}
根据业务特点调整:
nginx复制proxy_connect_timeout 5s;
proxy_send_timeout 10s;
proxy_read_timeout 30s;
可能原因及解决方案:
| 现象 | 可能原因 | 解决方案 |
|---|---|---|
| 间歇性502 | 后端SSL握手失败 | 检查后端证书有效期 |
| 持续502 | 证书验证失败 | 临时设置proxy_ssl_verify off排查 |
| 特定URI 502 | SNI配置问题 | 设置proxy_ssl_server_name on |
ss -ti检查连接状态bash复制nginx -V 2>&1 | grep -o with-http_stub_status_module
nginx复制ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
在error_log中关注以下关键词:
certificate verify failedSSL_do_handshake() failedno suitable certificate found可以使用grep过滤相关日志:
bash复制grep -E "SSL|certificate" /var/log/nginx/error.log
不同Nginx版本对SSL代理的支持:
| 版本 | 关键特性 |
|---|---|
| 1.7.0+ | 基础HTTPS代理支持 |
| 1.9.0+ | 支持SNI |
| 1.11.0+ | 增强的SSL配置选项 |
| 1.15.0+ | 支持TLS 1.3 |
建议使用1.18.0以上版本以获得完整的SSL代理功能支持。