Nginx ssl_verify_client不支持映射变量及SNI TLS终止配置问题
Nginx基于SNI的TLS终止配置问题及解决
问题背景
需配置基于SNI名称的Nginx TLS终止服务,解密后将流量转发至明文TCP应用,要求部分域名强制客户端证书认证。环境为nginx/1.22.1、Debian 6.1.90-1。
核心报错分析
执行配置校验命令nginx -t时,触发错误:
invalid value "$svc" in /etc/nginx/sites-enabled/default:24
原因是Nginx的ssl_verify_client指令不支持使用变量赋值,尝试重命名变量、显式赋值、嵌套if块均无法绕过该限制。后续ssl_client_certificate指令也出现同类报错,改用固定证书文件后配置校验通过,但SNI映射逻辑完全失效。
SNI映射失效的场景排查
- listen指令带ssl参数:日志中无SNI识别记录,映射变量未被正确赋值,导致证书匹配失败
- listen指令不带ssl参数:可正常识别SNI,但Nginx未执行TLS终止操作,直接转发明文流量,导致连接失败
- 添加
ssl_pre_read on:配置语法合法,但未实现预期的SNI映射与TLS终止联动效果
可行解决方案
由于ssl_verify_client、ssl_client_certificate这类TLS核心指令不支持变量,需通过按SNI拆分server块的方式实现需求:
配置示例
stream { # 针对需客户端证书认证的域名,单独配置server块 server { listen 443 ssl; server_name secure.example.com internal.example.net; # 服务端证书配置 ssl_certificate /etc/nginx/ssl/server_cert.pem; ssl_certificate_key /etc/nginx/ssl/server_key.pem; # 开启客户端证书校验并指定CA证书 ssl_verify_client on; ssl_client_certificate /etc/nginx/ssl/client_ca.crt; ssl_verify_depth 2; # 转发至后端明文TCP服务 proxy_pass backend_app:8080; } # 针对无需客户端证书的域名,单独配置server块 server { listen 443 ssl; server_name public.example.com guest.example.net; ssl_certificate /etc/nginx/ssl/server_cert.pem; ssl_certificate_key /etc/nginx/ssl/server_key.pem; ssl_verify_client off; proxy_pass backend_app:8080; } # 默认兜底server,处理未匹配的SNI请求 server { listen 443 ssl default_server; ssl_certificate /etc/nginx/ssl/default_cert.pem; ssl_certificate_key /etc/nginx/ssl/default_key.pem; return 403; } }
配置说明
- 每个server块通过
server_name匹配特定SNI域名,独立配置TLS校验规则 - 需确保所有server块的
listen指令均带ssl参数,保证Nginx执行TLS终止 - 若需管理大量域名,可将不同类型的server块拆分至单独配置文件,通过
include指令引入,提升维护性
内容的提问来源于stack exchange,提问作者user25750813
相关产品推荐
相关产品推荐

