跳到主要内容
ecdsa.com
git over HTTPS with libcurl + OpenSSL (Git for Windows default, macOS Homebrew, Alpine, RHEL)Git

错误信息

fatal: unable to access 'https://git.example.com/team/app.git/': SSL certificate problem: self-signed certificate in certificate chain

也可能输出为

  • fatal: unable to access 'https://git.example.com/team/app.git/': SSL certificate OpenSSL verify result: self-signed certificate in certificate chain (19)
  • SSL certificate problem: self signed certificate in certificate chain

消息中的 URL 是你的远程仓库地址。基于 OpenSSL 1.1.1 的构建版本打印不带连字符的“self signed”;libcurl 8.22 打印的是“SSL certificate OpenSSL verify result: self-signed certificate in certificate chain (19)”。

含义

Git 服务器(或位于它前面的某个组件)发送了一条完整的证书链,这条链终止于一张自签名根证书,而该根证书不在 git 所用 libcurl 的 CA 证书包中。如果访问 github.com 这样的公共主机时出现这种情况,这张根证书几乎总是属于你所在网络中执行 TLS 检查的代理;如果是自托管服务器,则属于公司 CA。

原因

修复方法

  1. 1.

    弄清这是谁的根证书

    打印某个公共主机的证书链。如果最上层的证书以你所在公司或某家安全厂商命名,说明连接正在被检查,git 需要信任的正是这张根证书。如果完全认不出它,就不要信任:先调查清楚。

    bash
    openssl s_client -connect github.com:443 -servername github.com -showcerts </dev/null 2>/dev/null \
      | grep -E '^ *[0-9]+ s:|^ *i:'
    # A root named after your company or a security vendor = interception proxy
  2. 2.

    Windows:使用 Windows 证书存储

    设置了 http.sslBackend schannel 的 Git for Windows 会信任 Windows 信任的一切,而在受管机器上,这已经包括代理的根证书。

    bash
    # Git for Windows: use the Windows certificate store, which already trusts the proxy root
    git config --global http.sslBackend schannel
  3. 3.

    将根证书添加到 git 使用的证书包中

    http.sslCAInfo 会替换默认证书包,因此要构建一个文件,同时包含公共根证书以及代理或公司的根证书。

    bash
    # Linux/macOS/WSL: append the proxy root to a bundle that keeps the public roots
    cat /etc/ssl/certs/ca-certificates.crt corp-proxy-root.pem > ~/.config/git/ca-bundle.pem
    git config --global http.sslCAInfo ~/.config/git/ca-bundle.pem
  4. 4.

    在 Linux 上把根证书安装到整个系统

    update-ca-certificates 会一次性为 git、curl、wget、pip 和大多数其他工具添加该根证书。

    bash
    sudo cp corp-proxy-root.pem /usr/local/share/ca-certificates/corp-proxy-root.crt
    sudo update-ca-certificates
  5. 5.

    临时诊断:只对一条命令跳过验证

    仅用于确认诊断结果。在实际工作中禁用验证,等于把你的 Git 凭证和源代码交给终止该连接的任何一方。

    bash
    # Diagnostic only, for one command
    git -c http.sslVerify=false ls-remote https://git.example.com/team/app.git

相关错误

浏览完整的签名错误库