跳到主要内容
ecdsa.com
Go crypto/x509Go

错误信息

x509: certificate relies on legacy Common Name field, use SANs instead

也可能输出为

  • tls: failed to verify certificate: x509: certificate relies on legacy Common Name field, use SANs instead

在 TLS 拨号中(Go 1.20+),这段文本前面会加上“tls: failed to verify certificate: ”,HTTP 客户端还会加上“Get \"https://…\": ”。用 Go 构建的程序(kubectl、Terraform、Docker、Prometheus、Vault CLI)打印的是同样的文本。

Go crypto/x509 — HostnameError for a certificate without subjectAltName (Go 1.15+)

含义

服务器证书没有主题备用名称(SAN)扩展,因此主机名只出现在主体的通用名称中。按照 RFC 6125 和 CA/Browser Forum 的规则,Go 从 Go 1.15 开始不再接受通用名称中的主机名(自 1.17 起完全不接受),并且在 CN 本来可以匹配时会明确说明这一点。修复方法是使用带 SAN 的证书;客户端已经没有可以打开的开关了。

原因

修复方法

  1. 1.

    确认缺少 SAN 扩展

    打印服务器所提供证书的主体和 subjectAltName。

    bash
    echo | openssl s_client -connect api.example.com:443 -servername api.example.com 2>/dev/null \
      | openssl x509 -noout -subject -ext subjectAltName
    # No "X509v3 Subject Alternative Name" in the output -> reissue the certificate
  2. 2.

    带上 subjectAltName 重新签发

    把每个 DNS 名称(如果客户端使用 IP 地址,也包括 IP 地址)都写进 subjectAltName。用 openssl x509 -req 签名 CSR 时,除非传入 -copy_extensions copy 或 -extfile,否则 CSR 中的扩展会被丢弃。

    bash
    openssl req -new -key server.key -subj "/CN=api.example.com" \
      -addext "subjectAltName=DNS:api.example.com" -out server.csr
    # when signing with "openssl x509 -req", keep the extension:
    openssl x509 -req -in server.csr -CA ca.pem -CAkey ca.key -days 90 -copy_extensions copy -out server.pem
  3. 3.

    不要寻找 Go 的开关

    临时的 GODEBUG=x509ignoreCN=0 应急开关已在 Go 1.17 中移除,因此重新签发证书是唯一的修复方法。

    text
    GODEBUG=x509ignoreCN=0 only worked in Go 1.15–1.16 and was removed in Go 1.17;
    there is no switch left in current Go releases. The certificate must carry SANs.

相关错误

浏览完整的签名错误库