Go crypto/x509Go
错误信息
x509: certificate is not valid for any names, but wanted to match api.example.com
也可能输出为
- tls: failed to verify certificate: x509: certificate is not valid for any names, but wanted to match api.example.com
“wanted to match”后面的名称就是你连接的目标。对于完全没有 SAN 扩展的证书,Go 报出的则是“x509: certificate relies on legacy Common Name field, use SANs instead”(前提是 CN 本来可以匹配)。
Go crypto/x509 — HostnameError for a certificate with no DNS SANs (e.g. IP-only or empty SAN list)
含义
Go 尝试将主机名与证书匹配,却根本找不到任何 DNS 名称:SAN 扩展是存在的,但只包含 IP 地址(或其他类型的条目),而通用名称不在考虑范围内。Go 会报告证书不覆盖任何名称,后面跟着它想要匹配的名称。
原因
为 IP 地址生成的证书被用于主机名
常见为节点或虚拟机地址生成的证书(只有 IP 类型的 SAN),后来改为通过 DNS 名称访问。
证书原本用于别的用途
偶见客户端证书、电子邮件(S/MIME)证书或代码签名证书不包含 DNS 类型的 SAN,不能用作服务器证书。
服务器提供了错误的证书
偶见服务器被误配置了客户端证书或内部证书,这通常发生在密钥轮换之后。
修复方法
- 1.
检查 SAN 条目和证书用途
SAN 列表显示存在哪些类型的名称;extendedKeyUsage 显示它到底是不是服务器证书。
bash echo | openssl s_client -connect api.example.com:443 -servername api.example.com 2>/dev/null \ | openssl x509 -noout -subject -ext subjectAltName,extendedKeyUsage - 2.
签发带 DNS 类型 SAN 的服务器证书
写入客户端使用的 DNS 名称;如果客户端也通过地址连接,再加上 IP 条目。
bash openssl req -new -key server.key -out server.csr -subj "/CN=api.example.com" \ -addext "subjectAltName=DNS:api.example.com,IP:10.0.0.5" - 3.
或者通过证书中列出的地址连接
只有当客户端连接的正是该 IP 时,IP 类型的 SAN 才会匹配。
go // If the certificate is meant for the IP address, dial the IP (it is matched against IP SANs) resp, err := client.Get("https://10.0.0.5:8443/")