Python запрашивает request.exceptions.SSLError: [Errno 8] _ssl.c: 504: EOF произошел с нарушением протокола
Я на Ubuntu 12.10 с OpenSSL 1.0.1c, python 2.7.3, Requests 1.0.3 и 1.0.4 (попробовал оба), и при попытке подключиться к веб-сайту в переменной url со следующим кодом.
def SendInitialRequest(xmlmessage, redirecturl):
url = 'https://centineltest.cardinalcommerce.com/maps/txns.asp'
payload = 'cmpi_msg=' + ET.tostring(xmlmessage)
headers = {
'Content-Type': 'application/x-www-form-urlencoded',
}
r = requests.post(url, data=payload, headers=headers, verify=None)
print r.text
Он выдает следующую ошибку:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "clams/libs/centinel/thinclient.py", line 134, in SendInitialRequest
r = requests.post(url, data=payload, headers=headers, verify=None)
File "/home/jasonamyers/.virtualenv/clams/lib/python2.7/site-packages/requests/api.py", line 87, in post
return request('post', url, data=data, **kwargs)
File "/home/jasonamyers/.virtualenv/clams/lib/python2.7/site-packages/requests/api.py", line 44, in request
return session.request(method=method, url=url, **kwargs)
File "/home/jasonamyers/.virtualenv/clams/lib/python2.7/site-packages/requests/sessions.py", line 269, in request
resp = self.send(prep, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies)
File "/home/jasonamyers/.virtualenv/clams/lib/python2.7/site-packages/requests/sessions.py", line 364, in send
r = adapter.send(request, **kwargs)
File "/home/jasonamyers/.virtualenv/clams/lib/python2.7/site-packages/requests/adapters.py", line 163, in send
raise SSLError(e)
requests.exceptions.SSLError: [Errno 8] _ssl.c:504: EOF occurred in violation of protocol
Попытка соединения с openssl возвращает следующее:
$ openssl s_client -connect centineltest.cardinalcommerce.com:443
CONNECTED(00000003)
140019346777760:error:140790E5:SSL routines:SSL23_WRITE:ssl handshake failure:s23_lib.c:177:
---
no peer certificate available
---
No client certificate CA names sent
---
SSL handshake has read 0 bytes and written 226 bytes
---
New, (NONE), Cipher is (NONE)
Secure Renegotiation IS NOT supported
Compression: NONE
Expansion: NONE
---
Если я заставляю его использовать tls1, он работает (вывод усечен):
$ openssl s_client -tls1 -connect centineltest.cardinalcommerce.com:443
CONNECTED(00000003)
depth=2 C = US, O = "thawte, Inc.", OU = Certification Services Division, OU
verify error:num=20:unable to get local issuer certificate
verify return:0
---
Я видел многочисленные отчеты об ошибках; однако я не нашел способ обойти это, используя библиотеку запросов python. Любая помощь будет принята с благодарностью.
Ответы
Ответ 1
Отправляя это здесь для других из страницы с вопросом о проблемах:
Запросы 'не поддерживают это до версии 1. После версии 1 вы должны подклассифицировать HTTPAdapter так:
from requests.adapters import HTTPAdapter
from requests.packages.urllib3.poolmanager import PoolManager
import ssl
class MyAdapter(HTTPAdapter):
def init_poolmanager(self, connections, maxsize, block=False):
self.poolmanager = PoolManager(num_pools=connections,
maxsize=maxsize,
block=block,
ssl_version=ssl.PROTOCOL_TLSv1)
Когда вы это сделаете, вы можете сделать это:
import requests
s = requests.Session()
s.mount('https://', MyAdapter())
Любой запрос через этот объект сеанса будет использовать TLSv1.
Ответ 2
Установка проверки = False только пропускает проверку сертификата сервера, но не поможет разрешить ошибки протокола SSL.
Эта проблема, вероятно, связана с отключением SSLv2 на веб-сервере, но Python 2.x по умолчанию пытается установить соединение с PROTOCOL_SSLv23. Это происходит при https://github.com/python/cpython/blob/360aa60b2a36f5f6e9e20325efd8d472f7559b1e/Lib/ssl.py#L1057
Вы можете обезвредить ssl.wrap_socket() в модуле ssl, переопределив параметр ключевого слова ssl_version. Следующий код может использоваться как есть. Поместите это в начале вашей программы перед выполнением любых запросов.
import ssl
from functools import wraps
def sslwrap(func):
@wraps(func)
def bar(*args, **kw):
kw['ssl_version'] = ssl.PROTOCOL_TLSv1
return func(*args, **kw)
return bar
ssl.wrap_socket = sslwrap(ssl.wrap_socket)
Ответ 3
Установка "дополнительных" пакетов безопасности для requests
решена для меня:
sudo apt-get install libffi-dev
sudo pip install -U просит [безопасность]
Ответ 4
Это известная ошибка, вы можете ее обработать с помощью взлома:
Откройте site-packages/requests/packages/urllib3/connectionpool.py
(или иначе просто сделайте локальную копию запросов внутри вашего собственного проекта) и измените блок, который говорит:
def connect(self):
# Add certificate verification
sock = socket.create_connection((self.host, self.port), self.timeout)
# Wrap socket using verification with the root certs in
# trusted_root_certs
self.sock = ssl_wrap_socket(sock, self.key_file, self.cert_file,
cert_reqs=self.cert_reqs,
ca_certs=self.ca_certs,
server_hostname=self.host,
ssl_version=self.ssl_version)
в
def connect(self):
# Add certificate verification
sock = socket.create_connection((self.host, self.port), self.timeout)
# Wrap socket using verification with the root certs in
# trusted_root_certs
self.sock = ssl_wrap_socket(sock, self.key_file, self.cert_file,
cert_reqs=self.cert_reqs,
ca_certs=self.ca_certs,
server_hostname=self.host,
ssl_version=ssl.PROTOCOL_TLSv1)
В противном случае, я полагаю, что где-то хуже, чем менее хаки, но я не мог найти его с несколькими взглядами.
ПРИМЕЧАНИЕ. В боковом канале requests
из PIP (1.0.4) на MacOS работает только с указанным вами URL-адресом.
Ответ 5
Я столкнулся с этой ошибкой, и исправление, похоже, отключает SNI, которое не поддерживает Python 2.7:
http://bugs.python.org/issue5639
urllib3 на ошибке python 2.7 SNI в Google App Engine
Ответ 6
Людям, которые не могут работать над исправлениями.
Придется изменить файл ssl.py, чтобы исправить его.
Найдите функцию create_default_context и измените строку:
context = SSLContext(PROTOCOL_SSLv23)
к
context = SSLContext(PROTOCOL_TLSv1)
Может кто-то может создать более простое решение без редактирования ssl.py?
Ответ 7
У меня была такая же проблема:
поднять SSLError (e)
request.exceptions.SSLError: [Errno 8] _ssl.c: 504: EOF произошел с нарушением протокола
У меня был скрипач, я остановил захват скрипача и не видел этой ошибки. Может быть из-за скрипача.
Ответ 8
К сожалению, принятый ответ не сработал у меня. В качестве временного обходного пути вы также можете использовать verify=False
при подключении к защищенному веб-сайту.
Из Запросы Python, вызывая SSLError
requests.get('https://example.com', verify=True)
Ответ 9
У меня была эта ошибка при подключении к серверу RabbitMQ MQTT через TLS. Я уверен, что сервер поврежден, но в любом случае он работал с OpenSSL 1.0.1, но не OpenSSL 1.0.2.
Вы можете проверить свою версию на Python, используя следующую команду:
import ssl
ssl.OPENSSL_VERSION
Я не уверен, как понизить OpenSSL в Python (по крайней мере, он статически связан с Windows), кроме использования более старой версии Python.
Ответ 10
У меня была аналогичная проблема, и я думаю, что если мы просто проигнорируем проверку ssl
, она будет работать как прелесть, поскольку это сработало для меня. Таким образом, подключение к серверу с помощью схемы https
, но указание им не проверять сертификат.
Использование requests
. Просто укажите verify=False
вместо None
requests.post(url, data=payload, headers=headers, verify=False)
Надеясь, что это будет работать для тех, кто нуждается:).