单个Nginx实例支持多个泛域名证书独立匹配,关键在于每个泛域名必须对应独立server块,且证书SAN须显式包含该块全部server_name(如*.a.com和a.com),私钥权限600、路径隔离,并通过SNI严格比对。

单个 Nginx 实例可以支持多个泛域名证书的独立匹配,但关键不在于“泛域名”本身有多灵活,而在于每个泛域名必须对应一个**独立、完整、隔离的 server 块**,且该块所用证书必须实际覆盖其 server_name 中声明的所有域名(包括根域与子域)。Nginx 不会自动推导或复用泛域名逻辑,它只在 TLS 握手阶段严格比对 SNI 名称与当前 server 块的 首个 server_name 是否落在证书的 SAN 列表中。
每个泛域名需独占一个 server 块
不能把 *.a.com 和 *.b.net 写进同一个 server 块里——哪怕都监听 443 ssl。Nginx 只加载该块指定的那套证书,而一张证书不可能同时合法覆盖两个无关主域。正确做法是:
- 为
*.a.com单独建一个 server 块,server_name写*.a.com a.com(根域必须显式加入,否则不生效) - 为
*.b.net单独建另一个 server 块,server_name写*.b.net b.net - 两个块都写
listen 443 ssl http2;,不可混用非 ssl 的 listen
证书必须真实包含对应泛域+根域
Let’s Encrypt 等主流 CA 发放的通配符证书默认不包含根域名。例如:certbot -d *.a.com 生成的证书只覆盖 www.a.com、api.a.com,但不覆盖 a.com。浏览器访问 a.com 时仍会报证书错误。
解决方法是在申请时一并带上根域:
certbot --nginx -d a.com -d *.a.comcertbot --nginx -d b.net -d *.b.net- 证书文件中 SAN 字段应同时含
a.com和*.a.com
路径与权限必须一一对应、互不干扰
两个泛域名证书不能共用同一组 ssl_certificate 路径。即使内容相同,Nginx 启动时也不会报错,但运行时只会按配置顺序加载第一个块的证书作为 fallback,其余块若路径错误或权限不足,会导致对应域名 HTTPS 请求失败(如连接重置、证书不匹配)。
推荐结构:
-
/etc/nginx/ssl/a.com/fullchain.pem+privkey.pem -
/etc/nginx/ssl/b.net/fullchain.pem+privkey.pem - 每个 server 块中的
ssl_certificate指向各自目录
验证是否真正独立匹配
不要只靠浏览器访问,用 OpenSSL 直接测试 TLS 层行为:
-
openssl s_client -connect your.ip:443 -servername www.a.com -showcerts 2>/dev/null | openssl x509 -noout -subject→ 应显示 CN = *.a.com -
openssl s_client -connect your.ip:443 -servername shop.b.net -showcerts 2>/dev/null | openssl x509 -noout -subject→ 应显示 CN = *.b.net - 换一个未配置的域名(如
c.org),应返回第一个 server 块的证书(或 default_server 块)


















