命令行工具

CondaSSLError:conda 证书报错的原因和正确修法

作者: · 最后核实

报错信息CondaSSLError: Encountered an SSL error. Most likely a certificate verification issue.

CondaSSLError: Encountered an SSL error. Most likely a certificate verification issue. 的意思是:conda 访问频道时 HTTPS 证书校验失败。 下面打印的 Exception: 那一行是具体原因,最常见的是代理重新签名 HTTPS 导致的 CERTIFICATE_VERIFY_FAILED。另一种变体 OpenSSL appears to be unavailable on this machine 则表示 Python 的 ssl 模块加载失败。用 ssl_verify: truststore 或 CA 证书包解决信任问题,不要把 ssl_verify 设成 false。

这条报错是什么意思

CondaSSLError 有两种消息,分别对应证书信任失败和 Python 的 ssl 模块加载不了。conda 下载 repodata.json 时,requests 库可能抛出 SSLError。conda 的 repodata 代码接着会检查能否导入 Python 的 ssl 模块,然后以两种消息之一抛出 CondaSSLError:

CondaSSLError: Encountered an SSL error. Most likely a certificate verification issue.

Exception: HTTPSConnectionPool(host='repo.anaconda.com', port=443): Max retries exceeded with url: ... (Caused by SSLError(SSLCertVerificationError(1, '[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate (_ssl.c:1006)')))
CondaSSLError: OpenSSL appears to be unavailable on this machine. OpenSSL is required to
download and install packages.

第一种是信任问题,和 requests 的 Max retries exceeded 相同;第二种是安装环境有问题,大多出现在 Windows 上。两种情况的修法不同:前者要解决“信任谁”,后者要解决“OpenSSL 能不能加载”,所以先看清楚报的是哪一句。

常见原因(按出现频率排序)

CondaSSLError 多数由代理解密 HTTPS 引起,其余 4 种原因按下面的顺序排查。

1. 有代理在解密 HTTPS

conda 文档直接点名了这种情况:企业代理会拦截加密流量,干扰 conda 和 pip 的连接,应该把代理的证书配置好,让 requests 能识别它。

  • 确认:
openssl s_client -connect repo.anaconda.com:443 -servername repo.anaconda.com </dev/null 2>/dev/null | openssl x509 -noout -issuer

签发者是公司名称或安全厂商,就可以确认。见企业 SSL 解密导致的报错。

  • 修复: IT 已经把根证书装进 Windows 或 macOS 的,用 conda config --set ssl_verify truststore;否则让 ssl_verify 指向包含该根证书的 PEM 证书包。

2. 没有激活环境就运行 conda(Windows)

conda 排错文档解释过:Windows 通过 PATH 查找 DLL,较新的 conda 和 Python 要求先激活环境,让 Library\bin 等目录进入 PATH。不激活,Python 就加载不了 OpenSSL,于是出现 “OpenSSL appears to be unavailable” 这种变体,或者 Can't connect to HTTPS URL because the SSL module is not available。

  • 确认: 在同一个终端里运行 python -c "import ssl; print(ssl.OPENSSL_VERSION)",会失败。
  • 修复: 使用 Anaconda Prompt,或者执行一次 conda init powershell(或 cmd.exe),然后重新打开终端。

3. ssl_verify 指向的文件不存在或不对

.condarc 里留着旧路径、文件是 DER 格式而不是 PEM,或者证书包里只有公司根证书、而有些频道并没有被解密。

  • 确认: conda config --show ssl_verify,检查文件是否存在、是否以 -----BEGIN CERTIFICATE----- 开头。
  • 修复: 用绝对路径指向一个“公开根证书 + 公司根证书”的 PEM 证书包,或者改用 truststore。

4. 频道或镜像地址本身有证书问题

内网服务器上的自建频道用了私有 CA,或者镜像地址的证书和主机名对不上。Exception 行会出现 Hostname mismatch 或者镜像的主机名。

  • 修复: 改正频道地址,或者把内网 CA 加进 ssl_verify 的证书包。

5. base 环境太老

很老的安装包自带的 CA 证书包可能已经过时,新近启用的公开根证书它不认识,访问某些频道就会失败。用 truststore 时会改用系统证书库;否则等网络恢复后,在 base 里更新一次 ca-certificates 和 certifi。

分平台修复命令

各平台的修法都是让 conda 信任正确的根证书:系统证书库里已有就用 ssl_verify: truststore,否则让 ssl_verify 指向 CA 证书包。

Windows(IT 已下发公司根证书):

conda config --set ssl_verify truststore
conda config --show ssl_verify

macOS:

conda config --set ssl_verify truststore        # 使用 macOS 系统信任设置

Linux:

sudo cp company-root.crt /usr/local/share/ca-certificates/ && sudo update-ca-certificates   # Debian/Ubuntu
conda config --set ssl_verify /etc/ssl/certs/ca-certificates.crt

任意系统,只对当前终端(conda 文档介绍的方式):

export REQUESTS_CA_BUNDLE=/path/to/company-bundle.pem

国内镜像: 下载慢可以按清华镜像站的说明在 ~/.condarc 里配置镜像,注意地址都是 https://:

channels:
  - defaults
show_channel_urls: true
default_channels:
  - https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/main
  - https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/r
  - https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/msys2
custom_channels:
  conda-forge: https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud

改完执行 conda clean -i 清除索引缓存。镜像站使用的是正规证书,配置正确时不需要改动 ssl_verify;如果换了镜像仍然报 CondaSSLError,问题就在本机或公司网络,而不在镜像。

多人共用的机器、CI 和镜像: conda 会从多个位置读取 .condarc,包括全系统的配置文件,比如 Linux 上的 /etc/conda/.condarc、Windows 上的 C:/ProgramData/conda/.condarc。把 ssl_verify 写在这里,或者把 .condarc 打包进构建镜像,所有用户和每个流水线任务就会使用相同的信任设置。用 conda config --show-sources 可以列出每个配置文件以及它设置了哪些值;某个角落里被遗忘的 ssl_verify: false 是很常见的意外。

高校和企业内网: 不少高校、科研院所和公司的出口有统一的上网认证或安全网关。如果在宿舍或办公室报错、在家里正常,基本可以确定是网络出口在解密 HTTPS 或者需要先认证。先在浏览器里打开任意 HTTPS 网站,看是否跳转到认证页面;再按上面的 openssl s_client 命令看证书签发者,向网络管理部门索取根证书,而不是关闭校验。

不推荐:关闭证书校验

执行 conda config --set ssl_verify false 能让报错消失,代价是下载并执行的软件包失去防篡改保护。conda 文档写明,把 ssl_verify 设为 False 会关闭连接的正常安全保护,不推荐这样做;关于禁用 SSL 的页面还警告,这样做意味着通过一条无法确认安全的连接下载并执行任意代码。安装包里的代码会在安装时运行,能篡改连接的人就能替换它们。

更安全的替代办法:用 ssl_verify: truststore 复用系统证书库;用 ssl_verify: /path/bundle.pem 指定特定 CA;用 REQUESTS_CA_BUNDLE 只影响当前终端;Windows 上先激活环境,让 OpenSSL 能正常加载。

怎么确认已经修好

修好之后,清掉索引缓存再执行 conda search 能正常返回结果:

conda config --show ssl_verify
conda clean -i
conda search python --info | head -5

conda clean -i 清掉缓存的索引,让下一条命令重新下载 repodata。搜索应当返回结果,不再出现 CondaSSLError。如果你自己托管频道,用 SSL 检测工具或证书链补全工具检查它的证书链。

常见问题

ssl_verify 对 conda 环境里的 pip 也有效吗?

无效。pip 有自己的设置(pip config set global.cert、PIP_CERT 或 --cert)。pip 24.2 起,在 Python 3.10+ 上会同时使用系统证书库和 certifi,所以把根证书装进操作系统,conda(用 truststore)和 pip 都能解决。见 pip 证书验证失败。

可以用 REQUESTS_CA_BUNDLE 代替 ssl_verify 吗?

可以。conda 通过 requests 库下载,conda 文档“使用非标准证书”一页就介绍了把 REQUESTS_CA_BUNDLE 设成包含公司根证书的 PEM 文件。写在 .condarc 里的 ssl_verify 更容易在不同终端之间保持一致。

设置 ssl_verify: truststore 被拒绝,为什么?

它需要 conda 23.9.0 及以上,并且 base 环境是 Python 3.10 及以上,因为它依赖 truststore 包。在 base 环境里检查 conda --version 和 python --version;版本太老就改用 PEM 证书包路径。

换成清华镜像能解决 CondaSSLError 吗?

只有原来的频道地址本身有问题时才有用。如果是网络里的代理在重新签名 HTTPS,访问任何频道(包括镜像)都会以同样的方式失败,必须先让 conda 信任代理的根证书。

资料来源

  1. conda docs: Settings (ssl_verify)
  2. conda docs: Using non-standard certificates
  3. conda docs: Troubleshooting (SSL connection errors)
  4. conda source: gateways/repodata/__init__.py (CondaSSLError)
  5. 清华大学开源软件镜像站 Anaconda 帮助