排错指南

证书不包含这个域名:ERR_CERT_COMMON_NAME_INVALID 的几种成因

浏览器提示证书不适用于该网站,或者拿到了另一个站点的证书。

这个错误的含义很窄:服务器发来的证书是有效的,只是上面没有你正在访问的这个域名。链是好的、没过期、CA 也受信任 —— 唯独名字不对。

同一个报错有好几种完全不同的成因,其中一种(拿到了同一台服务器上另一个站点的证书)光看错误信息看不出来。下面按从最常见到最少见的顺序排。

先看清服务器到底发了哪张证书

这一步能直接分出「证书签少了」和「拿错了证书」两大类:

# 带 SNI(正常访问的样子)
openssl s_client -connect example.com:443 -servername example.com </dev/null 2>/dev/null \
  | openssl x509 -noout -subject -ext subjectAltName

# 不带 SNI(看这台机器的默认站点是谁)
openssl s_client -connect example.com:443 -noservername </dev/null 2>/dev/null \
  | openssl x509 -noout -subject

-noservername 不能省。OpenSSL 1.1.1 及以上会自动按 -connect 的主机名填 SNI,所以不显式关掉的话,两条命令测的是同一件事。

对照结果:

两条命令的结果指向的成因
一样,而且证书上没有你的域名证书签少了名字 → 看下面第 1、2 节
不一样SNI 路由没配对,你的请求落到了默认站点 → 第 3 节
证书上有你的域名,但仍然报错拿到的证书不是你以为的那张 → 第 4 节(CDN / 负载均衡)

1. 泛域名不覆盖主域名

证书里只有 *.example.com,而访客访问的是 example.com。这是最常见的一种,因为它看起来完全不像证书问题 —— 所有子域名都正常,只有主域名坏。

详细解释和修法见泛域名为什么不覆盖主域名

2. 少签了 www,或者少签了新加的域名

证书是 SAN 证书,能签多少个名字取决于签发时写了多少个。常见的漏签:

  • 只签了 example.com,没签 www.example.com(或者反过来)。
  • 后来上线了新域名 / 换了品牌域名,DNS 指过来了,证书没重签。
  • 多个域名指向同一个站点(主域名、短域名、旧域名),证书只签了其中一个。

修法是重新签一张包含全部域名的证书。一张证书装得下多个名字,不需要一个域名一张。

别指望用 301 跳转绕过去:TLS 握手在 HTTP 之前完成,握手时证书就已经被拒绝了,跳转规则根本执行不到。

3. SNI 没配对,你拿到了别人的证书

一台服务器上跑多个 HTTPS 站点时,服务器靠握手里的 SNI 字段决定发哪张证书。如果没有任何一个站点的域名配置与请求的域名匹配,服务器不会报错 —— 它会发出默认站点的证书。于是访客看到的是一个完全无关的域名。

上面第二条命令返回的主题,就是这台机器的默认站点。如果那是另一个项目的域名,问题就在这里。逐项检查:

  • server_name 写全了吗。 nginx 里请求域名必须命中某个 server 块的 server_name;命不中就落到 default_server
  • 新站点的配置真的被加载了吗。 nginx -T 打印出的是实际生效的完整配置,比 ls sites-enabled/ 可靠 —— 忘了做软链、或者软链断了,都会让配置看起来存在而实际没加载。
  • 监听的地址对不对。 listen 443 ssl 写在了另一个 IP 上、或者 IPv6 只配了一半(访客走 AAAA 记录进来,落到没配的那条监听上),都会绕开你以为会命中的那个块。
  • 客户端是不是不发 SNI。 极老的客户端(Windows XP 上的 IE、Java 6)不发 SNI,一定会拿到默认站点的证书。这种情况没法在服务器端修,只能给那个站点单独一个 IP。

4. CDN、负载均衡、云上的证书绑定

接了 CDN 或负载均衡之后,访客握手的对象是边缘节点,不是你的源站。这时候有两张独立的证书,两处都可能出问题:

  • 边缘证书没绑,或者绑错了域名。 加了新域名却只在 DNS 上指了过去,忘了在 CDN 控制台给这个域名绑证书 —— 边缘会拿默认证书应付,症状和上面的 SNI 问题一样。
  • 源站证书的域名和回源 Host 不一致。 回源时如果开了「校验源站证书」,源站证书里必须有回源使用的那个 Host 名字,而不是访客看到的域名。这两个经常不是同一个。

5. 用 IP 或内网名访问

直接访问 https://1.2.3.4 或者 https://内网机器名 时报这个错,是正常的 —— 公开 CA 不给 IP 和内网名签发证书,证书里当然不会有它们。这不是故障,是用错了地址:用域名访问就好。

确实需要用 IP 校验源站时,用 --resolve 指定 IP 但仍以域名握手:

curl -v --resolve example.com:443:1.2.3.4 https://example.com/

6. 只有 CN,没有 SAN

很老的证书、或者自己用 openssl req 手工签的证书,可能只在 CN 字段里写了域名而没有 SAN 扩展。现在的浏览器完全忽略 CN(Chrome 自 58 版起),所以这种证书对所有域名都报不匹配。

重新签发时必须带上 SAN 扩展。任何公开 CA 现在签出来的证书都一定有 SAN,这种情况基本只出现在自签证书上。

常见问题

检测一下你自己的域名

免登录,一次真实的 TLS 握手,直接给出结论:还有多少天到期、证书链是否完整、是否包含这个域名。

需要一张新证书?本站提供基于 Let's Encrypt 的免费签发,支持泛域名。

了解免费证书

其他排错指南

Last updated on