最可靠的方式是直接调用x509_check_host,它专为rfc 6125设计,支持通配符、idn及大小写处理,返回1表示匹配、0不匹配、负数为错误;手动提取dns名需遍历san中gen_dns条目并校验ia5string编码。

OpenSSL中用X509_check_host验证域名是否匹配证书
直接调用 X509_check_host 是最可靠的方式,它专为 RFC 6125 域名匹配设计,比手动解析 subjectAltName 或比对 CN 更安全、更标准。该函数在 OpenSSL 1.0.2+ 可用,1.1.1+ 默认启用国际化域名(IDN)处理。
常见错误是跳过此函数,转而用 strcmp 直接比对 CN 字段——这既忽略 SAN(现代证书几乎都不依赖 CN),也不处理通配符、大小写、空格或 IDN 编码问题。
- 必须传入非空、以
\0结尾的 ASCII 域名字符串(如"api.example.com"),不支持 UTF-8 原始域名;若需处理中文域名,应先调用idn_to_ascii_8z转换 - 第四个参数
flags至少要包含X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS,否则*.example.com会错误匹配www.sub.example.com - 返回 1 表示匹配,0 表示不匹配,负数表示内部错误(如内存分配失败、证书无 DNS 名等)
如何提取证书的 DNS 名列表并手动比对(备用方案)
当无法使用 X509_check_host(如旧版 OpenSSL 或嵌入式环境),就得自己遍历 subjectAltName 扩展中的 GEN_DNS 条目。注意:不能只看 commonName,RFC 2818 已明确废弃其用于域名验证。
关键步骤是用 X509_get_ext_d2i 提取 NID_subject_alt_name,再用 GENERAL_NAMES 遍历每个 GENERAL_NAME,对类型为 GEN_DNS 的条目调用 ASN1_STRING_get0_data 获取原始字节,并确认其编码为 IA5String(即 ASCII 兼容)。
-
ASN1_STRING_type必须是V_ASN1_IA5STRING,否则可能是畸形数据或 UTF8String(需额外转换) - 返回的 DNS 名可能含前导/尾随空格,需用
strspn+strcspn截取有效子串 - 通配符仅允许出现在最左侧(
*.example.com),且仅匹配单段子域;**.example.com或*.sub.example.com都不合法
libcurl 中开启严格证书域名验证的配置项
如果你用的是 libcurl,别以为设置了 CURLOPT_SSL_VERIFYPEER 为 1 就够了——默认情况下,libcurl 不会校验域名,必须显式启用 CURLOPT_SSL_VERIFYHOST。
-
CURLOPT_SSL_VERIFYHOST设为2L(推荐),表示同时验证证书有效性与域名匹配;设为1L是旧版兼容模式,已弃用且行为不一致 - 若服务端返回的证书 Subject 中
CN是 IP 地址(如CN=192.168.1.1),即使启用了VERIFYHOST,libcurl 也不会用它做域名检查——它只查 SAN 中的IPAddress条目 - 自定义 CA 证书路径需通过
CURLOPT_CAINFO或CURLOPT_CAPATH显式指定,否则系统默认信任库可能缺失中间证书,导致验证失败而非域名不匹配
常见失败场景和调试建议
遇到 “certificate verify failed” 却不确定是证书链问题还是域名不匹配,优先检查 SSL_get_verify_result 返回值:若为 X509_V_ERR_CERT_NOT_VALID_FOR_NAME,就是域名不匹配;若为 X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY,才是证书链缺失。
- 用
openssl x509 -in cert.pem -text -noout查看证书实际包含的 DNS 名,确认目标域名是否在Subject Alternative Name列表中 - 客户端发起连接时,SNI(Server Name Indication)未发送或发送错误域名,会导致服务端返回错误证书(如默认站点证书),此时域名匹配必然失败
- 测试时用
curl -v https://wrong-name.example.com观察 verbose 输出里的* SSL certificate verify result:行,比代码调试更快定位问题类型
域名匹配逻辑看似简单,但通配符边界、IDN 处理、SAN 优先级、SNI 同步这些点一旦漏掉一个,就可能让整个 TLS 验证形同虚设。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











