Python requests请求Let's Encrypt站点报SSLCertVerificationError问题
问题描述
在Python 3.8环境中执行以下代码发起HTTPS请求:
import requests requests.get("https://e-sat.de/")
执行后抛出如下SSL验证错误:
requests.exceptions.SSLError: HTTPSConnectionPool(host='e-sat.de', 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:1131)')))
同一站点通过浏览器访问时证书状态完全正常。尝试使用certifi提供的CA Bundle,通过verify参数指定本地证书路径发起请求:
import requests requests.get("https://e-sat.de/", verify="path/to/certs.pem")
依然复现相同报错。目前多个使用Let's Encrypt签发证书的站点均存在相同问题,由于站点证书会动态变更,无法手动逐个配置站点证书,需要明确问题触发原因与通用解决方案。
问题根因
该问题和Let's Encrypt的根证书切换直接相关:
- Let's Encrypt原依赖的DST Root CA X3根证书已于2021年9月过期,后续默认使用ISRG Root X1作为新的信任根。
- 浏览器内置的根证书库会自动更新,同时支持证书链自动补全、交叉签名兼容逻辑,因此访问不受影响。
- Python 3.8环境下如果安装的
certifi版本低于2021.10.08,内置的CA根证书库没有收录ISRG Root X1根证书,就会触发"无法找到本地颁发者证书"的验证错误。手动指定旧版certifi生成的certs.pem文件时,因为文件本身缺少对应根证书,依然会报错。
可行解决方案
按推荐优先级从高到低排列:
- 升级依赖版本(优先推荐)
直接将requests和certifi升级到最新版本,升级后不需要手动指定verify参数,requests会自动调用新版certifi中包含ISRG Root X1的信任库完成验证,所有Let's Encrypt签发的站点均可正常访问。执行命令:
升级后可执行pip install --upgrade requests certifipip show certifi确认版本号不低于2021.10.8即可。 - 受环境限制无法升级依赖时手动补全根证书
如果生产环境锁定了依赖版本无法升级,可以将ISRG Root X1根证书内容直接追加到你当前使用的certs.pem文件末尾(不要删除原有证书内容),一次修改后所有使用Let's Encrypt证书的站点均可正常验证,不需要逐个站点配置证书。 - 临时调试方案(禁止生产环境使用)
本地临时调试时可以将verify参数设为False临时跳过证书验证,该方式会关闭SSL证书校验逻辑,存在中间人攻击风险,绝对不能在生产环境使用。示例代码:import requests requests.get("https://e-sat.de/", verify=False)
内容的提问来源于stack exchange,提问作者orangenhaft
相关产品推荐
相关产品推荐

