使用古怪的服务器上的请求“发生违反协议的EOF”

安德鲁·哈里森(Andrew Harrison)

问题

我需要使用Pythonrequests连接到运行过时配置的服务器这是SSL Labs关于服务器配置的报告尽管尝试了我在StackOverflow,GitHub问题和@Lukasa自己的博客上阅读的几乎所有解决方案,但我仍然遇到以下错误:

requests.exceptions.SSLError: HTTPSConnectionPool(host='public.cdpehs.com', port=443): Max retries exceeded with url: /ILENVPBL/ESTABLISHMENT/ShowESTABLISHMENTTablePage.aspx?ESTTST_CTY=asgGk3ztR6c%3D (Caused by SSLError(SSLEOFError(8, u'EOF occurred in violation of protocol (_ssl.c:590)'),))

我尝试过的

根据现有答案,我尝试了

  • 安装requests[security]idnapyopensslpyasn1,和ndg-httpsclient通过pip
  • 改变ssl_versionPoolManager在安装自定义适配器
  • 更改的密码套件ssl_contextPoolManager在安装自定义适配器

这是我的测试脚本的最新版本:

import requests
import ssl
from requests.packages.urllib3.util.ssl_ import create_urllib3_context
from urllib3.poolmanager import PoolManager
from requests.adapters import HTTPAdapter

class DESAdapter(HTTPAdapter):
    def init_poolmanager(self, connections, maxsize, block=False, *args, **kwargs):
        CIPHERS = (
            'ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:ECDH+HIGH:'
            'DH+HIGH:ECDH+3DES:DH+3DES:RSA+AESGCM:RSA+AES:RSA+HIGH:RSA+3DES:!aNULL:'
            '!eNULL:!MD5:DES-CBC3-SHA'
        )
        context = create_urllib3_context(ciphers=CIPHERS)  # also tried 'ALL'
        kwargs['ssl_context'] = context
        self.poolmanager = PoolManager(
            num_pools=connections, 
            maxsize=maxsize, 
            block=block, 
            ssl_version=ssl.PROTOCOL_TLSv1, 
            *args, 
            **kwargs
        )

sess = requests.Session()
sess.mount('https://', DESAdapter())
res = sess.get('https://public.cdpehs.com/ILENVPBL/ESTABLISHMENT/ShowESTABLISHMENTTablePage.aspx?ESTTST_CTY=asgGk3ztR6c%3D')

诊断信息

如果我正确阅读了SSL Labs报告(如上链接),则仅为TLSv1 /配置了此服务器TLS_RSA_WITH_3DES_EDE_CBC_SHA该密码套件与DES-CBC3-SHA 根据OpenSSL docs对应在报告的“握手模拟”部分下,我注意到OpenSSL 1.0.x的结果列为“服务器关闭的连接”,这似乎令人担忧。

OpenSSL详细信息:

$ openssl version
OpenSSL 1.0.2g-fips  1 Mar 2016

$ openssl ciphers -v | grep DES | sort | head -5
DES-CBC3-SHA            SSLv3 Kx=RSA      Au=RSA  Enc=3DES(168) Mac=SHA1
DH-DSS-DES-CBC3-SHA     SSLv3 Kx=DH/DSS   Au=DH   Enc=3DES(168) Mac=SHA1
DH-RSA-DES-CBC3-SHA     SSLv3 Kx=DH/RSA   Au=DH   Enc=3DES(168) Mac=SHA1
ECDH-ECDSA-DES-CBC3-SHA SSLv3 Kx=ECDH/ECDSA Au=ECDH Enc=3DES(168) Mac=SHA1
ECDHE-ECDSA-DES-CBC3-SHA SSLv3 Kx=ECDH     Au=ECDSA Enc=3DES(168) Mac=SHA1

Python细节:

$ python --version
Python 2.7.12

$ pip list
asn1crypto (0.24.0)
backports.ssl-match-hostname (3.5.0.1)
cached-property (1.4.2)
certifi (2018.4.16)
cffi (1.11.5)
chardet (3.0.4)
crcmod (1.7)
cryptography (2.2.2)
docker (3.3.0)
docker-compose (1.21.2)
docker-pycreds (0.2.3)
dockerpty (0.4.1)
docopt (0.6.2)
enum34 (1.1.6)
functools32 (3.2.3.post2)
idna (2.7)
ipaddress (1.0.22)
jsonschema (2.6.0)
ndg-httpsclient (0.5.0)
pip (8.1.2)
psycopg2 (2.7.4)
pyasn1 (0.4.3)
pycparser (2.18)
pyOpenSSL (18.0.0)
python-apt (1.1.0b1)
PyYAML (3.12)
requests (2.19.0)
setuptools (20.7.0)
six (1.11.0)
texttable (0.9.1)
urllib3 (1.23)
websocket-client (0.47.0)
wheel (0.29.0)

包含升级软件包的解决方案是可行的,但我不愿升级,除非成功的可能性很大。

哥恩67

对于您创建的自定义HTTPAdapter子类,我做了一个小的修改,看起来很有效:

import ssl

import requests
from requests.adapters import HTTPAdapter
from requests.packages.urllib3.util.ssl_ import create_urllib3_context
from requests.packages.urllib3.poolmanager import PoolManager


class DESAdapter(HTTPAdapter):
    def init_poolmanager(self, connections, maxsize, block=False, *args, **kwargs):
        CIPHERS = (
            'ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:ECDH+HIGH:'
            'DH+HIGH:ECDH+3DES:DH+3DES:RSA+AESGCM:RSA+AES:RSA+HIGH:RSA+3DES:!aNULL:'
            '!eNULL:!MD5:DES-CBC3-SHA'
        )

        context = create_urllib3_context(ssl_version=ssl.PROTOCOL_TLSv1)
        context.set_ciphers(CIPHERS)

        self.poolmanager = PoolManager(
            num_pools=connections,
            maxsize=maxsize,
            block=block,
            ssl_context=context,
            *args,
            **kwargs
        )

sess = requests.Session()
sess.mount('https://', DESAdapter())
res = sess.get('https://public.cdpehs.com/ILENVPBL/ESTABLISHMENT/ShowESTABLISHMENTTablePage.aspx?ESTTST_CTY=asgGk3ztR6c%3D')
print res

调用时ssl_.create_urllib3_context,您可以传入要使用的协议。在这种情况下,我们需要TLSv1:ssl_.create_urllib3_context(ssl_version=ssl.PROTOCOL_TLSv1)

这可能是ssl_versionssl_context不能在同一时间使用PoolManager构造函数。似乎ssl_version有优先权,因此如果设置了优先权,那么它将ssl_context被忽略。因此,请确保ssl_versionPoolManager构造函数中删除


我注意到您已经安装了PyOpenSSL。

如果安装了PyOpenSSL,我发布的DESAdapter代码似乎无法正常工作。我不确定为什么会这样。

我确实知道,requests如果已安装它将使用pyOpenSSL。否则requests将依赖ssl于python中的标准模块。我相信使用pyOpenSSL的原因之一是在2.7中支持SNI。但是我相信SNI支持在2.7.12中可用。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章