Nginx实现“一机多证”依赖TLS的SNI扩展,需确保OpenSSL≥1.0.2、每个域名独占server块并配置专属证书、80端口重定向HTTPS、用openssl s_client验证SNI响应正确。

Nginx 实现“一机多证”(即单 IP、单 443 端口下为多个域名各自提供独立 SSL 证书),核心依赖 TLS 协议的 SNI 扩展,而不是靠 Nginx 主动“开启”某个开关——只要环境满足,它就自动生效。 关键不在“怎么打开 SNI”,而在于**确保 SNI 能被正确触发和响应**。下面分四点说清楚怎么做:
确认底层支持:OpenSSL 版本与 Nginx 编译
运行 nginx -V 2>&1 | grep -i openssl,输出中必须包含 OpenSSL ≥1.0.2(推荐 1.1.1+),且不能显示 BoringSSL 或无版本信息。
若不满足,需升级 OpenSSL 并重新编译 Nginx,或换用官方预编译包(如 Ubuntu/Debian 的 nginx-full、CentOS 的 EPEL nginx)。
无需手动加 ssl_protocols 或 ssl_ciphers 来“启用 SNI”,那是无效操作。
每个域名配一个独立 server 块
不能把多个域名塞进同一个 server 块来“共用证书”,也不能让多个 server 块指向同一组 ssl_certificate 路径——Nginx 启动不报错,但只加载第一个块的证书,其余全 fallback 到它。
正确做法是:
- 每个域名(或一组强关联子域)单独写一个
server块 - 每个块都写
listen 443 ssl http2; -
server_name必须与对应证书的 SAN 列表或 CN 完全一致(例如证书含site-a.com和www.site-a.com,就写server_name site-a.com www.site-a.com;) -
ssl_certificate和ssl_certificate_key路径必须严格指向该域名专属的 PEM 文件(如/etc/letsencrypt/live/site-a.com/fullchain.pem)
HTTP 请求统一跳转 HTTPS
为每个域名补一个 80 端口的 server 块,强制重定向:
- 写
listen 80;+ 对应的server_name - 用
return 301 https://$host$request_uri;,不拼接硬编码域名 - 避免用
rewrite,简洁可靠
上线前必做验证
别只测浏览器访问,要直击 TLS 层:
- 用 OpenSSL 检查 SNI 是否生效:
openssl s_client -connect your.ip:443 -servername site-a.com -showcerts 2>/dev/null | openssl x509 -noout -text | grep -A1 "Subject Alternative Name" - 确认返回的证书确实包含
site-a.com,且不是其他域名的证书 - 再换
site-b.net测试,结果应不同 - 执行
nginx -t通过后再nginx -s reload











