应使用san或通配符证书,配置单个https server块,server_name包含所有域名,ssl_certificate等指令仅设一次,并确保证书san字段完整覆盖各域名,同时配置hsts、tls版本限制等安全策略及default_server兜底。

在 Nginx 中让多个域名共享同一张 SSL 证书,关键不是“虚拟主机数量”,而是证书类型与 server 块结构的匹配。真正安全、稳定且符合现代 TLS 实践的做法,是使用 SAN(Subject Alternative Name)证书 或 通配符证书,并配合一个明确的 HTTPS server 块——而非为每个域名建独立 server 块再复用证书路径。
用一个 server 块承载所有目标域名
这是最简洁、最不易出错的方式,适用于子域统一管理、品牌关联站点或 API 多端点等场景:
- 所有域名写在同一行的
server_name指令中,用空格分隔,不加逗号或引号 -
ssl_certificate和ssl_certificate_key只需指定一次,指向同一份 SAN 证书的 fullchain.pem 和 privkey.pem - 确保该证书的 SAN 字段显式包含每个域名,例如:
DNS:example.com, DNS:www.example.com, DNS:api.example.com - 裸域(example.com)和带 www 的域名必须同时列出,否则访问 www 版本会触发证书不匹配警告
确保证书覆盖完整,避免常见陷阱
证书本身是策略落地的前提。配置再正确,证书缺项就直接失效:
- 通配符
*.example.com只匹配一级子域(如www、api),不覆盖example.com本身,也不覆盖a.b.example.com - 若需同时支持
example.com和*.example.com,申请时必须把两者都加入 SAN 列表 - 验证方法:运行
openssl x509 -in /path/to/cert.pem -text -noout | grep -A1 "Subject Alternative Name",确认输出中含全部目标域名 - Let’s Encrypt 申请多域名证书命令示例:
certbot certonly --nginx -d example.com -d www.example.com -d api.example.com
补充必要安全配置,不能只靠证书
仅启用 HTTPS 不代表安全。以下指令应作为标配写入该 server 块:
-
ssl_protocols TLSv1.2 TLSv1.3;—— 禁用已知不安全的 TLSv1.0/TLSv1.1 -
ssl_ciphers设置强加密套件,优先选用 ECDHE + AES-GCM 组合 -
ssl_session_cache shared:SSL:10m; ssl_session_timeout 10m;—— 启用会话复用,降低 TLS 握手开销 -
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;—— 强制 HSTS,防止协议降级 - 另配一个
listen 80;server 块,用return 301 https://$host$request_uri;实现 HTTP 自动跳转
避免默认 server 干扰与证书泄漏
当请求 Host 不匹配任何 server_name,Nginx 会交给该端口下第一个定义的 server 块处理。若这个块绑的是某业务证书,就会造成“证书错配”或“域名泄露”:
- 在所有业务 server 块之前,显式定义一个兜底的
default_server - 该块监听
443 ssl default_server,server_name _;,使用仅含服务器 IP 的自签名证书 - 返回
return 444;(静默关闭连接),不暴露任何真实域名或服务信息 - 所有租户或业务 server 块均不加
default_server标识,仅靠server_name精准匹配











