" EOF发生违反协议"在wonky服务器上使用请求

时间:2018-06-13 19:21:11

标签: python-2.7 openssl python-requests

问题

我需要使用Python requests包连接到运行过期配置的服务器。这是服务器配置的the report from 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]
  • 安装idnapyopensslpyasn1ndg-httpsclientpip
  • 更改已安装的自定义适配器中的ssl_version的{​​{1}}
  • 更改已安装的自定义适配器中PoolManager的{​​{1}}的密码套件

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

ssl_context

诊断信息

如果我正确阅读了SSL实验室报告(上面已链接),则此服务器仅配置为TLSv1 / PoolManager。此密码套件与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') according to OpenSSL docs对应。根据"握手模拟"在报告部分,我注意到OpenSSL 1.0.x结果列为"服务器已关闭连接",这似乎有关。

OpenSSL详细信息:

TLS_RSA_WITH_3DES_EDE_CBC_SHA

Python详细信息:

DES-CBC3-SHA

需要升级套餐的解决方案是可行的,但除非有很高的成功可能性,否则我不愿意升级。

1 个答案:

答案 0 :(得分:0)

对于您创建的自定义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_version构造函数中删除PoolManager

我注意到你安装了PyOpenSSL。

如果安装了PyOpenSSL,我发布的DESAdapter代码似乎不起作用。我不知道为什么会这样。

我知道requests如果安装了pyOpenSSL将会使用它。否则requests将依赖python中的标准ssl模块。我相信使用pyOpenSSL的一个原因是2.7中的SNI支持。但我相信SNI的支持可以在2.7.12中找到。