nginx 多域名 https 通过独立 server 块配置 sni 实现,需 openssl ≥1.0.2、nginx ≥1.11.0 且启用 ssl_module;每个 server 块须指定专属证书路径与匹配的 server_name,https 和 http 配置分离,验证需用 openssl s_client 检查 sni 分发。

直接在 Nginx 里为每个域名配独立的 server 块,各自指定证书路径和 server_name,只要 OpenSSL ≥1.0.2 且 Nginx ≥1.11.0,SNI 就自动生效——不用额外开关,也不用改协议或加密套件。
确认底层支持 SNI
这是前提,很多人卡在这步却没意识到:
- 运行
nginx -V 2>&1 | grep -i openssl,输出必须含类似OpenSSL 1.1.1w或3.0.13的版本号;若显示BoringSSL或无输出,说明不支持 SNI,需换官方预编译包或重编译 - 确保 Nginx 编译时启用了
--with-http_ssl_module(主流发行版默认满足) -
listen 443 ssl这一行本身已隐式启用 SNI,无需加ssl_protocols等指令来“开启”它
每个域名一套证书 + 一个 server 块
不能图省事合并配置,必须严格一一对应:
- 用 Certbot 分别申请:比如
certbot --nginx -d site-a.com和certbot --nginx -d site-b.net,会在/etc/letsencrypt/live/下生成隔离目录 - 每个
server块内写明专属路径:ssl_certificate /etc/letsencrypt/live/site-a.com/fullchain.pem;ssl_certificate_key /etc/letsencrypt/live/site-a.com/privkey.pem; -
server_name必须与证书 SAN 字段完全一致:比如证书含site-a.com和www.site-a.com,就写server_name site-a.com www.site-a.com; - 禁止多个
server块共用同一组ssl_certificate路径——Nginx 不报错,但只加载第一个块的证书,其余全 fallback
监听与跳转要分开处理
HTTPS 和 HTTP 的逻辑要清晰拆开:
- 所有 HTTPS 站点统一
listen 443 ssl http2;,但证书、密钥、server_name全部保留在各自server块内 - 通用 SSL 参数(如
ssl_protocols、ssl_ciphers、ssl_dhparam)可提至http块复用,但 绝不能把ssl_certificate放到http块 - 为每个域名单独配 80 端口跳转:
server { listen 80; server_name site-a.com; return 301 https://$host$request_uri; }
验证是否真正生效
别只看浏览器绿锁,要确认 SNI 是否按域名精准分发:
- 用 OpenSSL 模拟握手:
openssl s_client -connect site-a.com:443 -servername site-a.com -showcerts 2>/dev/null | openssl x509 -noout -subject
结果应显示CN = site-a.com;换成site-b.net应显示对应 CN - 执行
nginx -t检查语法,再nginx -s reload生效 - 老旧客户端(如 WinXP IE6、部分 IoT 设备)不发 SNI,Nginx 会用第一个定义的
server块证书响应——如有必要,可显式定义一个兜底default_server











