错误信息
ERROR: The certificate of 'api.example.com' is not trusted.
也可能输出为
- ERROR: The certificate of 'api.example.com' doesn't have a known issuer.
只有使用 GnuTLS 构建的 wget 会打印这两行。使用 OpenSSL 构建的版本(Ubuntu 22.04 及更高版本、Alpine、Fedora 的 wget 1.x)把同样的情况报告为“ERROR: cannot verify <host>'s certificate, issued by '…'”,后面接着“Unable to locally verify the issuer's authority.”。
含义
Debian 构建 wget 时使用的 TLS 库 GnuTLS 无法验证服务器的证书,因此 wget 拒绝下载。这第一行是通用的;wget 紧接着打印的那一行才指出实际原因,最常见的是“doesn't have a known issuer”(没有通向受信任根证书的路径)或“has expired”。wget 以退出状态 5(SSL 验证失败)退出。
原因
证书来自私有 CA
常见公司、实验室和 Kubernetes 的证书追溯到的根证书不在 Debian 的 ca-certificates 证书包中;GnuTLS 将此报告为颁发者未知。
服务器没有发送中间证书
常见GnuTLS 不会下载缺失的中间证书。如果服务器只配置了叶子证书,验证就会在这里失败,尽管浏览器会缓存和获取中间证书,并把该网站显示为安全。
执行 TLS 检查的代理对连接重新签名
偶见公司代理出示的是由其自有根证书签发的证书。除非这台机器(或容器)的系统证书包中安装了该根证书,否则每次 HTTPS 下载都会失败。
系统中没有 CA 证书包
偶见精简版 Debian 和 Ubuntu 镜像不包含 ca-certificates 证书包。这时即使是知名的公共网站,也会被判定为“not trusted”。
修复方法
- 1.
查看紧随其后的那一行
第二条 ERROR 报错才是真正的诊断。“doesn't have a known issuer”指向 CA 或证书链问题;“has expired”和“is not yet activated”指向日期问题;“owner does not match hostname”指向名称不匹配。
bash wget -O /dev/null https://api.example.com/ 2>&1 | grep '^ERROR' # ... is not trusted. # ... doesn't have a known issuer. <- chain/CA problem # ... has expired. <- date problem - 2.
告诉 wget 信任哪个 CA
--ca-certificate 接受一个包含一张或多张 CA 证书的 PEM 文件;在 ~/.wgetrc 或 /etc/wgetrc 中设置 ca_certificate 可以让它永久生效。--ca-directory 适用于以哈希命名的证书目录。
bash wget --ca-certificate=/opt/certs/corp-root-ca.pem https://api.example.com/ # permanently, for this user or system-wide (/etc/wgetrc) echo 'ca_certificate = /opt/certs/corp-root-ca.pem' >> ~/.wgetrc - 3.
把 CA 安装到系统证书包中
在 Debian 和 Ubuntu 上,放在 /usr/local/share/ca-certificates 中、扩展名为 .crt 的证书,会由 update-ca-certificates 添加到 /etc/ssl/certs/ca-certificates.crt,而 GnuTLS 默认读取的正是这个文件。
bash sudo cp corp-root-ca.pem /usr/local/share/ca-certificates/corp-root-ca.crt sudo update-ca-certificates # minimal images: install the bundle first apt-get install -y --no-install-recommends ca-certificates - 4.
服务器所有者:发送完整证书链
如果握手中只有一张证书,并且它的颁发者是中间 CA,就为服务器配置完整证书链文件。
bash # Server side: count the certificates in the handshake (1 = leaf only) openssl s_client -connect api.example.com:443 -servername api.example.com -showcerts </dev/null 2>/dev/null \ | grep -c 'BEGIN CERTIFICATE' - 5.
临时诊断:只跳过一次检查
--no-check-certificate 可以显示除信任之外是否还有其他问题。它会禁用全部证书验证,代理或攻击者因此可以悄无声息地替换你下载的内容;切勿把它用于安装程序或脚本。
bash # Diagnostic only: proves the download works when trust is ignored wget --no-check-certificate -O /dev/null https://api.example.com/
相关错误
ERROR: cannot verify api.example.com's certificate, issued by 'CN=Example Priva…GNU Wget built with OpenSSL (Ubuntu 22.04+, Alpine, RHEL/CentOS)ERROR: The certificate of 'api.example.com' has expired.GNU Wget built with GnuTLS (Debian)curl: (60) SSL certificate problem: unable to get local issuer certificatecurl (OpenSSL backend)fatal: unable to access 'https://git.example.com/team/app.git/': server verific…git over HTTPS with libcurl-gnutls (Debian, Ubuntu)