nginx 不选择证书,而是根据 server_name 匹配规则选定 server 块,再发送该块配置的 ssl_certificate;通配符证书生效的前提是其所在 server 块被 sni 匹配选中,而非证书自身具有优先级。

nginx 本身不参与 SSL/TLS 证书的选择逻辑——它不“匹配证书”,而是由 OpenSSL(或系统 TLS 库)在 TLS 握手阶段,根据客户端 ClientHello 中的 SNI(Server Name Indication)字段,从当前 server 块配置的证书中选出最合适的那个。
证书选择取决于 server 块,而非证书本身
nginx 的作用是:为每个 server 块明确指定 ssl_certificate 和 ssl_certificate_key。当请求到达某个 server 块时,nginx 就把该块里配置的证书发给客户端。所以“哪个证书被用上”,本质是由“请求最终落入哪个 server 块”决定的,而 server 块的选取规则,正是 server_name 的优先级匹配机制。
- 通配符证书(如
*.example.com)只是 PEM 文件内容,它本身不会自动绑定到*.example.com的请求上 - 必须有一个
server { server_name *.example.com; ssl_certificate ...; }块,且该块被成功选中,证书才会生效 - 同样,具体域名证书(如
www.example.com)也必须放在一个server_name www.example.com的块里才起作用
真正起作用的是 server_name 匹配优先级
假设你同时配置了以下三个 HTTPS server 块(监听 443 端口):
-
server_name example.com;→ 配置了example.com.crt -
server_name *.example.com;→ 配置了wildcard.example.com.crt -
server_name ~^([a-z]+)\.example\.com$;→ 配置了regex.example.com.crt
当客户端请求 www.example.com 时:
- 先尝试精确匹配:
example.com≠www.example.com→ 不命中 - 再找最长前缀通配符:
*.example.com完全匹配 → 该 server 块被选中 → 使用其配置的通配符证书 - 正则块根本不会执行(因通配符已命中)→ 其证书不参与本次握手
也就是说:通配符证书是否生效,不取决于它“更宽泛”,而取决于它所在的 server 块,在 server_name 匹配链中是否被优先选中。
常见配置陷阱与建议
- 不要把多个域名证书塞进同一个 server 块:nginx 不支持单个块内多证书自动切换(SNI 多证书需用
ssl_certificate_by_lua*或 OpenSSL 1.1.1+ 的ssl_trusted_certificate配合 OCSP Stapling,但非常规做法) - 避免通配符覆盖核心域名:若
server_name *.example.com;写在server_name example.com;前面,不影响匹配结果(因精确匹配永远优先),但容易误导维护者;建议按优先级从高到低组织顺序 - 测试实际使用的证书:用
openssl s_client -connect example.com:443 -servername www.example.com -showcerts查看返回的证书 subject 和 SAN 字段,确认是否为你预期的那个 - 注意 default_server:若未匹配任何
server_name,且 443 上有default_server,则会使用它的证书——这可能导致用户访问错域却拿到错误证书(如浏览器警告)
小结:证书没有独立优先级,只有 server 块有
所谓“通配符证书 vs 具体域名证书”的优先关系,其实是伪命题。真实链路是:
客户端 SNI → nginx 根据 server_name 规则选定 server 块 → nginx 发送该块配置的证书。
因此,确保你要用通配符证书响应的域名,确实落入了对应通配符 server_name 的块中;而关键业务域名(如 example.com、www.example.com)应使用精确匹配块并配专属证书,既安全又可控。











