Python 请求的问题 SSLCertVerificationError

Problem with Python requests SSLCertVerificationError

我想弄清楚,为什么我遇到一个问题,即 Python 代码在具有多个的虚拟主机上为有效 LetsEncrypt 证书抛出 SSLCertVerificationError域和证书在同一个 IP 如果我删除除一个证书之外的所有证书都很好,但是 有多个证书请求会忽略 Python 向其发送请求的域并提取most recent LetsEncrypt certificate,这是不正确的,导致域 SSLCertVerificationError.

我的理解是,在 SNI(服务器名称指示)下,请求应该只提取发出请求的域的证书,而不仅仅是最新的证书。我已经检查过,我 运行ning Python, 3.8, requests 2.5 under a version of Nginx that has been compiled with SNI 支持。我可以通过关闭 SSL 验证来抑制错误,但这似乎是一个糟糕的解决方法。

知道发生了什么事吗? 为什么当浏览器从 Nginx 请求页面时 SNI 工作正常,pullign 正确的证书,但在 Python 的请求包下完成同样的操作时失败? 我已经阅读了我能找到的所有内容,文档说它应该只在 nginxrequestsOpenSSL 等当前版本下工作,但显然不在这里。


要复制,我可以从本地机器上 requests.get{'https://kedrosky.org') 无差错。但是在该服务器(托管域)的脚本 运行 上,返回了错误域的较新证书,导致 SSLCertVerificationError。

问题是服务器配置可能只针对 IPv4 正确完成,即使域也解析为 IPv6 地址。对于 IPv4,return 是正确的证书:

 $ openssl s_client -connect kedrosky.org:443 -4
 ...
 subject=CN = kedrosky.com

但是对于 IPv6,它 return 是一个不同的证书(这需要 IPv6 连接到本地计算机上的互联网):

 $ openssl s_client -connect kedrosky.org:443 -6
 ...
 subject=CN = paulandhoward.com

这可能是因为只有 listen 443 而没有 listen [::]:443,IPv6 需要后者。在这种情况下,虚拟主机仅适用于 IPv4,但对于 IPv6,它将只是 return 默认值,即通常是配置的第一个证书。

您从不同主机看到不同结果的原因是一个只有 IPv4 连接,而另一个也可以连接 IPv6。