我想弄清楚,为什么我有一个问题,即Python
代码抛出SSLCertVerificationError
了有效的在同一个IP有多个域和证书的虚拟主机上LetsEncrypt证书如果我删除所有的证书,除了一个它的罚款,但有更多的多个证书请求会忽略Python向其发送请求的域,并拉取最近 LetsEncrypt certificate
的域(这是不正确的),从而导致该域SSLCertVerificationError
。
我的理解是,在SNI
(服务器名称指示)下的请求应仅提取请求所针对的域的证书,而不仅仅是最新的证书。我已经检查过,并且我正在运行3.8的Python,Nginx
并在经过SNI
支持的编译版本下请求2.5。我可以通过关闭SSL验证来抑制此错误,但这似乎是一个较差的解决方法。
知道发生了什么吗?SNI
当浏览器从Nginx
,请求正确的证书请求页面,而在Python的request包下完成同样的操作却失败时,为什么工作正常?我已经读到的一切我都能找到,而且文档说这应该只是工作在当前建立的nginx
,requests
,OpenSSL
等,但它显然不在这里。
为了进行复制,我可以从本地计算机上进行没有错误的request.get {'https://kedrosky.org')。但是,在该服务器(托管域)上运行的脚本上,将返回针对错误域的更新证书,从而导致SSLCertVerificationError。
问题在于,即使域也解析为IPv6地址,服务器配置也可能仅针对IPv4正确完成。使用IPv4,它将返回正确的证书:
$ openssl s_client -connect kedrosky.org:443 -4
...
subject=CN = kedrosky.com
但是使用IPv6时,它将返回不同的证书(这需要与本地计算机上的Internet进行IPv6连接):
$ openssl s_client -connect kedrosky.org:443 -6
...
subject=CN = paulandhoward.com
可能是因为IPv6只需要一个,而后者则listen 443
不是listen [::]:443
。在这种情况下,虚拟主机仅适用于IPv4,而使用IPv6时,它将仅返回默认值,即通常配置的第一个证书。
而且你从不同主机看到不同结果的原因是,一个主机仅具有IPv4连接,而另一个也可以进行IPv6。
非常感谢。显然这正是发生了什么。我现在在hosts文件中有listen指令来处理4和6,并且它正在运行。