python - 请求 SSL : CERTIFICATE_VERIFY_FAILED with verify ="./cabundle.crt"

标签 python ssl https python-requests

问题

简短描述:当使用自己的 cabundle 连接到服务器时,python 请求不断抛出 SSL: CERTIFICATE_VERIFY_FAILED:

In [1]:  import requests
In [3]: requests.get('https://activeo.monitowl.com', verify=True)      
Out[3]: <Response [200]>
In [4]: requests.get('https://activeo.monitowl.com', verify="./ca_bundle.crt")
---------------------------------------------------------------------------
SSLError                                  Traceback (most recent call last)
<ipython-input-3-c92a3091d6ce> in <module>()
----> 1 requests.get('https://activeo.monitowl.com', verify="./ca_bundle.crt")

/home/vagrant/.virtualenvs/test/local/lib/python2.7/site-packages/requests/api.pyc in get(url, params, **kwargs)
     67 
     68     kwargs.setdefault('allow_redirects', True)
---> 69     return request('get', url, params=params, **kwargs)
     70 
     71 

/home/vagrant/.virtualenvs/test/local/lib/python2.7/site-packages/requests/api.pyc in request(method, url, **kwargs)
     48 
     49     session = sessions.Session()
---> 50     response = session.request(method=method, url=url, **kwargs)
     51     # By explicitly closing the session, we avoid leaving sockets open which
     52     # can trigger a ResourceWarning in some cases, and look like a memory leak

/home/vagrant/.virtualenvs/test/local/lib/python2.7/site-packages/requests/sessions.pyc in request(self, method, url, params, data, headers, cookies, files, auth, timeout, allow_redirects, proxies, hooks, stream, verify, cert, json)
    463         }
    464         send_kwargs.update(settings)
--> 465         resp = self.send(prep, **send_kwargs)
    466 
    467         return resp

/home/vagrant/.virtualenvs/test/local/lib/python2.7/site-packages/requests/sessions.pyc in send(self, request, **kwargs)
    571 
    572         # Send the request
--> 573         r = adapter.send(request, **kwargs)
    574 
    575         # Total elapsed time of the request (approximately)

/home/vagrant/.virtualenvs/test/local/lib/python2.7/site-packages/requests/adapters.pyc in send(self, request, stream, timeout, verify, cert, proxies)
    429         except (_SSLError, _HTTPError) as e:
    430             if isinstance(e, _SSLError):
--> 431                 raise SSLError(e, request=request)
    432             elif isinstance(e, ReadTimeoutError):
    433                 raise ReadTimeout(e, request=request)

SSLError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:581)

In [5]: requests.get('https://activeo.monitowl.com', verify="./ca_bundle_ff.crt")    
[same error]
In [7]:  import ssl; ssl.OPENSSL_VERSION
Out[7]: 'OpenSSL 1.0.1k 8 Jan 2015'
In [8]: import sys; print (sys.version)
2.7.9 (default, Mar  1 2015, 12:57:24) 
[GCC 4.9.2]
In [2]: requests.__version__
Out[2]: '2.7.0'

故事

我们正在使用 MonitOwl 中的请求代理与 API 服务器通信。几天前,我们为 *.monitowl.com 订购了新证书并将其部署到新实例,我们的颁发者是 nazwa.pl。将网络浏览器指向 https://activeo.monitowl.com工作完美,请求似乎有一些问题,当设置 verify="./cabundle.crt"时。

技术说明

在处理 ssl 的 tornado 服务器前面有一个“透明”的 haproxy 检查 SNI 并重新分配流量,配置文件的一部分:

acl app_activeo req_ssl_sni -i activeo.monitowl.com
use_backend bk_activeo if app_activeo

我们需要提供自己的 cabundle 来控制接受的内容 - 因为安全问题和部署脚本。我们到处都在使用 debian jessie。

我用 ssl checker 测试了服务器除了接受旧的加密算法之外没有任何问题..

# from issuer https://panel.nazwa.pl/uploads/ssl/nazwaSSL_SHA-2.zip
$ cat monitowlcom.crt nazwasslsha2.pem certumca-ctncasha2.pem gscasha2.pem > ./ca_bundle.crt
# exported from firefox
$ cat monitowl.com nazwaSSL CertumTrustedNetworkCA CertumGlobalServicesCASHA2 > ca_bundle_ff.crt
$  openssl verify -untrusted ./ca.crt  monitowlcom.crt 
monitowlcom.crt: OK
$ c_rehash ./
$ openssl s_client -CApath ./  -connect activeo.monitowl.com:443 -servername activeo.monitowl.com
CONNECTED(00000003)
depth=4 C = PL, O = Unizeto Sp. z o.o., CN = Certum CA
verify return:1
depth=3 C = PL, O = Unizeto Technologies S.A., OU = Certum Certification Authority, CN = Certum Trusted Network CA
verify return:1
depth=2 C = PL, O = Unizeto Technologies S.A., OU = Certum Certification Authority, CN = Certum Global Services CA SHA2
verify return:1
depth=1 C = PL, O = nazwa.pl S.A., OU = http://nazwa.pl, CN = nazwaSSL
verify return:1
depth=0 C = PL, CN = *.monitowl.com, emailAddress = ***@whitehats.pl
verify return:1
[...]
*    Verify return code: 0 (ok)*

$ curl -I --cacert ca_bundle.crt https://activeo.monitowl.com 
HTTP/1.1 200 OK
$ curl -I --cacert ca_bundle_ff.crt https://activeo.monitowl.com 
HTTP/1.1 200 OK

如您所见,openssl s_client 验证连接,curl 工作正常。

在服务器端( Tornado ): SSLError: [SSL: TLSV1_ALERT_UNKNOWN_CA] tlsv1 警报未知 ca (_ssl.c:581)

我请一些 friend 使用从网络浏览器导出的包对其进行测试,并且:

Python==2.7.9 + OpenSSL==1.0.1k => FAILS
Python==2.7.10 + OpenSSL==1.0.1k => FAILS
Python==2.7.9 + OpenSSL==1.0.1l => FAILS
Python==2.7.10 + OpenSSL==1.0.1p => WORKS
Python==2.7.10 + OpenSSL==1.0.2d => WORKS
Python==2.7.9 + OpenSSL 1.0.2d  => WORKS

我知道 python 会验证证书 differently比网络浏览器,但看起来它不是这里的东西。

问题

您是否知道 bundle 出了什么问题? 我还能检查什么?

这是一个错误?在请求中,openssl、python 还是 urllib3?

最佳答案

不要使用你的 ca 包文件。尝试使用 verify=True 并将您的证书文件的内容粘贴到/usr/local/lib/python2.7/dist-packages/requests/cacert.pem 的底部,位置取决于您的Linux 版本或 dist(CentOS、Debian 等)。请使用find/-name requests 来定位requests 在您系统中的安装位置,然后找到cacert.pem。

这是因为 Requests 默认使用这个 cacert.pem 作为它自己的 ca 包。

如果这不起作用,那么您应该获取高级颁发者证书作为证书文件。

关于python - 请求 SSL : CERTIFICATE_VERIFY_FAILED with verify ="./cabundle.crt",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32761774/

相关文章:

python - 无法使用 Mechanize 下载网站内容

ssl - TFS 2017,HTTPS 绑定(bind)失去控制台权限?

ruby-on-rails - 如何为自定义子域禁用 SSL

http - Jetty 9.2.1 将 http 重定向到 https

php - SSL 证书错误 : insecure URLs and a form

ssl - 如果 SSL 被禁止会怎样?

python - 将 mysql 数据导出到 csv 时不要将 NULL 值转换为空字符串

python - 确保千克转换为克 pandas

python - 如何将列中的 k-means 预测聚类添加到 Python 中的数据框

java - 如何在 TrustManager 的 checkServerTrusted() 中获取 CertPathValidatorResult?