我需要使用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]
idna
,pyopenssl
,pyasn1
,ndg-httpsclient
和pip
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
需要升级套餐的解决方案是可行的,但除非有很高的成功可能性,否则我不愿意升级。
答案 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_version
和ssl_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中找到。