服务器和代理
AH01909:Apache 证书里没有和 ServerName 匹配的域名
AH01909: www.example.com:443:0 server certificate does NOT include an ID which matches the server nameAH01909 的意思是:Apache 的 mod_ssl 发现某个虚拟主机的证书里,没有这个虚拟主机的 ServerName。 它在加载配置时以警告级别记录,比如 AH01909: www.example.com:443:0 server certificate does NOT include an ID which matches the server name。Apache 照常启动,但用 ServerName 访问的客户端会看到域名不匹配的错误。最常见的原因是虚拟主机没写 ServerName、ServerName 写错了,或者证书文件指错了。
先读懂这条日志
“server certificate”前面那一段由虚拟主机信息拼成:ServerName:端口,再加 :序号 表示这是该虚拟主机里的第几张证书。以 www.example.com:443:0 为例:
| 部分 | 含义 |
|---|---|
www.example.com |
Apache 用来比较的 ServerName;没写 ServerName 时是它猜出来的名字 |
443 |
虚拟主机的端口 |
0 |
该虚拟主机里的第一张证书(1 表示第二张,比如 ECDSA 证书) |
mod_ssl 拿这个名字去和证书 SAN 里的 DNS 名称、以及证书的 CN 比较,通配符只匹配最左边一级,ServerAlias 里的名字不参与比较。
为什么 Apache 只是警告
Apache 没法知道客户端实际会用哪个名字访问:一个虚拟主机可能主要服务别名,可能在负载均衡后面按 IP 访问,也可能只是兜底,证书覆盖的是那些名字也说得通。所以 mod_ssl 只记一条警告继续运行。浏览器就没有这种宽容了:按 RFC 9525 和各浏览器自己的规则,客户端访问的名字不在证书 SAN 里就会拒绝连接。AH01909 是浏览器报 NET::ERR_CERT_COMMON_NAME_INVALID、SSL_ERROR_BAD_CERT_DOMAIN 之前,服务器一侧的预警。
同类 mod_ssl 启动日志
mod_ssl 加载证书时会记录几条同类日志,其中只有 AH02572 会让 Apache 无法启动。
| 代码 | 级别 | 日志内容(节选) | 含义 |
|---|---|---|---|
| AH01906 | 警告 | server certificate is a CA certificate | 把 CA 证书配成了服务器证书 |
| AH01907 | 警告 | server certificate is not a leaf certificate | 证书允许继续签发下级证书 |
| AH01909 | 警告 | server certificate does NOT include an ID which matches the server name | ServerName 不在证书里 |
| AH02572 | 紧急 | Failed to configure at least one certificate and key | 没有可用的证书和私钥,Apache 无法启动,见 AH02572 |
常见原因(按出现频率排序)
AH01909 有 4 种常见原因,最常见的是 SSL 虚拟主机没写 ServerName。
1. SSL 虚拟主机没写 ServerName
发行版自带的默认配置(Debian/Ubuntu 的 default-ssl.conf,CentOS、Rocky 等系统 mod_ssl 自带的 ssl.conf)里没有 ServerName。Apache 文档写明:基于名称的虚拟主机没有 ServerName 时,会使用由系统主机名推导出的完整域名。所以日志里出现的往往是 localhost、机器名或者反向解析出来的名字。如果同时看到 AH00558(“Could not reliably determine the server's fully qualified domain name”),说明全局 ServerName 也没设置。
2. 证书没覆盖 ServerName
虚拟主机写的是 ServerName example.com,证书却只签了 www.example.com;或者拿 *.example.com 通配符证书去配主域名。看证书里有哪些名字:
openssl x509 -in /etc/ssl/certs/example.com.crt -noout -subject -ext subjectAltName
3. 虚拟主机指向了错误的证书文件
续期或迁移之后,SSLCertificateFile 还指向旧证书、系统自带的占位证书(Debian/Ubuntu 上的 ssl-cert-snakeoil.pem),或者另一个网站的证书。看每个虚拟主机加载的是哪个文件:
apachectl -S
grep -RniE 'ServerName|SSLCertificateFile' /etc/apache2/sites-enabled/ /etc/httpd/conf.d/ 2>/dev/null
apachectl -S 会列出每个虚拟主机所在的文件和行号,443 端口上有多个虚拟主机时能快速定位。宝塔面板用 Apache 时,站点配置在面板的网站目录下,改动前先在面板里查看对应站点的 SSL 设置。
4. 故意设置的兜底虚拟主机
专门用来回应未知域名的默认虚拟主机,无论配哪张证书都会报 AH01909。知道它的存在就无所谓。
一台 Apache 跑多个 HTTPS 站点时要注意什么
同一个 IP 和 443 端口上配了多个虚拟主机时,Apache 按客户端在 SNI 里发来的域名,去匹配各虚拟主机的 ServerName 和 ServerAlias。Apache 文档写明:如果一个都匹配不上,就用这组虚拟主机里排在第一个的那个。由此带来两个后果:
- 某个站点的 ServerName 写错了,用户访问它时会落到第一个虚拟主机上,拿到的是别人的证书,浏览器报域名不匹配。
- 排在第一个的虚拟主机往往是系统默认站点,它的 AH01909 警告最常见,也最容易被忽略。
- Apache 文档说明,用通配符包含的配置文件按字母顺序加载,所以
000-default、default-ssl这类文件名会排在前面。想让某个站点做兜底,就让它的文件名排在最前;不想要兜底,就停用默认站点。
所以看到 AH01909 时,不要只盯着报警的那一个虚拟主机,最好用 apachectl -S 把 443 上所有虚拟主机的顺序和名字都过一遍,确认每个域名都能匹配到正确的虚拟主机和证书。
怎么修
每个 SSL 虚拟主机都要写明 ServerName,证书要覆盖它和所有 ServerAlias。
1. 每个 SSL 虚拟主机都写明 ServerName,其他名字写进 ServerAlias:
<VirtualHost *:443>
ServerName example.com
ServerAlias www.example.com
SSLEngine on
SSLCertificateFile /etc/letsencrypt/live/example.com/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/example.com/privkey.pem
</VirtualHost>
从 Apache 2.4.8 起,SSLCertificateFile 可以同时包含中间证书,直接指向完整证书链文件即可。
2. 申请覆盖所有名字的证书,ServerName 和 ServerAlias 里的都要有:
sudo certbot --apache -d example.com -d www.example.com
详见 Apache 配置 Let's Encrypt。宝塔用户可以在站点的“SSL”页面勾选所有域名重新申请,见 宝塔面板配置 SSL。
3. 设置全局 ServerName(apache2.conf 或 httpd.conf),让默认虚拟主机不再依赖系统主机名。
4. 停用用不到的默认 SSL 站点(Debian/Ubuntu 上执行 a2dissite default-ssl),它们通常只挂着占位证书。
怎么确认已经修好
修好的标志是错误日志里不再出现 AH01909,并且每个域名带 SNI 测试都拿到覆盖它的证书。
apachectl configtest返回Syntax OK,然后systemctl reload apache2(或httpd)。- 重载之后错误日志里不再出现 AH01909:
bash
grep AH01909 /var/log/apache2/error.log | tail -n 3
CentOS、Rocky 等系统的日志在 /var/log/httpd/ 下。
3. 带 SNI 逐个测试每个名字:openssl s_client -connect example.com:443 -servername www.example.com </dev/null 2>/dev/null | openssl x509 -noout -ext subjectAltName,再用 SSL 检测 检查每个域名。
常见问题
AH01909 可以不管吗?
只有在你清楚它为什么出现时可以,比如一个专门兜底、从不服务真实流量的默认虚拟主机。其他情况下,用 ServerName 访问的用户会看到 NET::ERR_CERT_COMMON_NAME_INVALID 这类域名不匹配错误。
证书是 *.example.com 通配符,为什么 example.com 还报 AH01909?
通配符只匹配最左边一级:*.example.com 能覆盖 www.example.com,覆盖不了 example.com,也覆盖不了 a.b.example.com。申请证书时把主域名单独加上。
AH01909 会检查 ServerAlias 吗?
不会,mod_ssl 只比较虚拟主机的 ServerName。ServerAlias 里的名字同样必须在证书里,但 Apache 不会为它们报警,要用 openssl s_client -servername 逐个测试。
虚拟主机标识最后的 :0 是什么意思?
是证书在该虚拟主机里的序号。同时配了 RSA 和 ECDSA 两张证书时,会看到 :0 和 :1,哪张证书缺域名就为哪张报一次。