Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

requests.exceptions.SSLError: EOF occurred in violation of protocol (_ssl.c:645) #3006

Closed
caizixian opened this issue Feb 12, 2016 · 77 comments

Comments

@caizixian
Copy link

Here is the first issue.
https://github.com/kennethreitz/requests/issues/2906

Python 3.5.1 (https://www.python.org/downloads/) Virtualenv 14.0.5 Mac OS X 10.11.3

First, I created a virtualenv and pip install requests[security]

Then I got

>>> from cryptography.hazmat.backends.openssl.backend import backend
>>> print(backend.openssl_version_text())
OpenSSL 1.0.2f  28 Jan 2016

which was what I expected.

Everything worked great for about an hour.

Then, some of my own scripts crashed which was normal. After that, when I try to run my script again, I got following exceptions

ssl.SSLEOFError: EOF occurred in violation of protocol (_ssl.c:645)

requests.packages.urllib3.exceptions.SSLError: EOF occurred in violation of protocol (_ssl.c:645)

requests.exceptions.SSLError: EOF occurred in violation of protocol (_ssl.c:645)

So I opened another Python console and

>>> requests.get("https://www.google.com")
<Response [200]>
>>> requests.get("https://www.telegram.org")
Traceback (most recent call last):
  File "VirtualenvPath/lib/python3.5/site-packages/requests/packages/urllib3/connectionpool.py", line 559, in urlopen
    body=body, headers=headers)
  File "VirtualenvPath/lib/python3.5/site-packages/requests/packages/urllib3/connectionpool.py", line 345, in _make_request
    self._validate_conn(conn)
  File "VirtualenvPath/lib/python3.5/site-packages/requests/packages/urllib3/connectionpool.py", line 784, in _validate_conn
    conn.connect()
  File "VirtualenvPath/lib/python3.5/site-packages/requests/packages/urllib3/connection.py", line 252, in connect
    ssl_version=resolved_ssl_version)
  File "VirtualenvPath/lib/python3.5/site-packages/requests/packages/urllib3/util/ssl_.py", line 305, in ssl_wrap_socket
    return context.wrap_socket(sock, server_hostname=server_hostname)
  File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/ssl.py", line 376, in wrap_socket
    _context=self)
  File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/ssl.py", line 747, in __init__
    self.do_handshake()
  File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/ssl.py", line 983, in do_handshake
    self._sslobj.do_handshake()
  File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/ssl.py", line 628, in do_handshake
    self._sslobj.do_handshake()
ssl.SSLEOFError: EOF occurred in violation of protocol (_ssl.c:645)

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "VirtualenvPath/lib/python3.5/site-packages/requests/adapters.py", line 376, in send
    timeout=timeout
  File "VirtualenvPath/lib/python3.5/site-packages/requests/packages/urllib3/connectionpool.py", line 588, in urlopen
    raise SSLError(e)
requests.packages.urllib3.exceptions.SSLError: EOF occurred in violation of protocol (_ssl.c:645)

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "VirtualenvPath/lib/python3.5/site-packages/requests/api.py", line 67, in get
    return request('get', url, params=params, **kwargs)
  File "VirtualenvPath/lib/python3.5/site-packages/requests/api.py", line 53, in request
    return session.request(method=method, url=url, **kwargs)
  File "VirtualenvPath/lib/python3.5/site-packages/requests/sessions.py", line 468, in request
    resp = self.send(prep, **send_kwargs)
  File "VirtualenvPath/lib/python3.5/site-packages/requests/sessions.py", line 576, in send
    r = adapter.send(request, **kwargs)
  File "VirtualenvPath/lib/python3.5/site-packages/requests/adapters.py", line 447, in send
    raise SSLError(e, request=request)
requests.exceptions.SSLError: EOF occurred in violation of protocol (_ssl.c:645)
>>> 

So I rebooted, uninstalled all these libs and pip install them again. Everything worked again.

But after 1 hour or so, same exception again.

@sigmavirus24
Copy link
Contributor

Then, some of my own scripts crashed which was normal.

What does a crash like that look like?

After that, when I try to run my script again, I got following exceptions

Are you completely unable to run them at all after that?

@caizixian
Copy link
Author

@sigmavirus24 It's just some bug in my own code without anything to do with networking.
I'm not sure whether this is the real cause or just coincidence.

But one thing is for sure, after some point, I'm completely unable to make request to https://www.telegram.org, which I can do right after install request.

Just FYI: #2906

@sigmavirus24
Copy link
Contributor

So I'd like to point out that you're installing requests[security] which means we should be using pyOpenSSL but your stacktrace shows that we aren't. That's intriguing.

@caizixian
Copy link
Author

@sigmavirus24 So this there anything I can do to help you?

@caizixian
Copy link
Author

Any idea? @Lukasa

@Lukasa
Copy link
Member

Lukasa commented Feb 12, 2016

So what matters most here is: why does your code stop using PyOpenSSL? When you encounter your crash, can you open a python console in your virtual environment and then run import urllib3.contrib.pyopenssl, to see if that works?

@caizixian
Copy link
Author

Couldn't reproduce it now. I will close this first, and if I encounter the problem again, I will paste the result and reopen it.

@caizixian
Copy link
Author

@Lukasa I think since requests is shipped with its own urllib3, I could not import urllib3 alone. And the following result confirms it.

Python 3.5.1 (v3.5.1:37a07cee5969, Dec  5 2015, 21:12:44) 
[GCC 4.2.1 (Apple Inc. build 5666) (dot 3)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import urllib3.contrib.pyopenssl
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ImportError: No module named 'urllib3'
>>> ^D




pip list
cffi (1.5.0)
cryptography (1.2.2)
idna (2.0)
ndg-httpsclient (0.4.0)
pip (8.0.2)
pyasn1 (0.1.9)
pycparser (2.14)
pyOpenSSL (0.15.1)
requests (2.9.1)
setuptools (20.0)
six (1.10.0)
wheel (0.26.0)

@Lukasa
Copy link
Member

Lukasa commented Feb 12, 2016

I'm sorry, try importing requests.packages.urllib3.contrib.pyopenssl

@caizixian
Copy link
Author

@Lukasa

Python 3.5.1 (v3.5.1:37a07cee5969, Dec  5 2015, 21:12:44) 
[GCC 4.2.1 (Apple Inc. build 5666) (dot 3)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import requests.packages.urllib3.contrib.pyopenssl
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "VirtualenvPath/lib/python3.5/site-packages/requests/packages/urllib3/contrib/pyopenssl.py", line 57, in <module>
    from socket import _fileobject, timeout, error as SocketError
ImportError: cannot import name '_fileobject'
>>> 

@sigmavirus24
Copy link
Contributor

I bet that is a bug on 3.5 with pyOpenSSL that we didn't know about @Lukasa (with respect to _fileobject not existing.

@Lukasa
Copy link
Member

Lukasa commented Feb 12, 2016

Nope, I know about it, and have proposed a fix upstream in urllib3 when we started testing PyOpenSSL. The reality is that requests[security] does not (and has never) worked on Python 3. That'll be fixed in an upcoming version of Requests.

So that doesn't solve our puzzle: why did this work for a bit and then stop?

@FirefighterBlu3
Copy link

tangent comment based on original report, the built in ssl.py in python has an option to suppress ragged EOFs as there are plenty of sites that will uncleanly shutdown SSL connections. sometimes unreliably as if it were a matter of timing or coincidence. the following is an extract from ssl.py

class SSLSocket(socket):
    [...]
    def read(self, len=0, buffer=None):
        """Read up to LEN bytes and return them.
        Return zero-length string on EOF."""

        self._checkClosed()
        if not self._sslobj:
            raise ValueError("Read on closed or unwrapped SSL socket.")
        try:
            return self._sslobj.read(len, buffer)
        except SSLError as x:
            if x.args[0] == SSL_ERROR_EOF and self.suppress_ragged_eofs:
                if buffer is not None:
                    return 0
                else:
                    return b''
            else:
                raise

@caizixian
Copy link
Author

@the-efi
Copy link

the-efi commented Feb 19, 2016

Having the same exception on Python 2.7.11/OSX when pounding a server with requests under gevent. Could this be related?

@sigmavirus24
Copy link
Contributor

@the-efi could you be more specific about which exception you're seeing?

@the-efi
Copy link

the-efi commented Feb 19, 2016

    r = requests.post(self.MY_URL, data=parameters)
  File "/Users/me/Envs/my_env/lib/python2.7/site-packages/requests/api.py", line 109, in post
    return request('post', url, data=data, json=json, **kwargs)
  File "/Users/me/Envs/my_env/lib/python2.7/site-packages/requests/api.py", line 50, in request
    response = session.request(method=method, url=url, **kwargs)
  File "/Users/me/Envs/my_env/lib/python2.7/site-packages/requests/sessions.py", line 465, in request
    resp = self.send(prep, **send_kwargs)
  File "/Users/me/Envs/my_env/lib/python2.7/site-packages/requests/sessions.py", line 573, in send
    r = adapter.send(request, **kwargs)
  File "/Users/me/Envs/my_env/lib/python2.7/site-packages/requests/adapters.py", line 431, in send
    raise SSLError(e, request=request)
SSLError: EOF occurred in violation of protocol (_ssl.c:590)

@Lukasa
Copy link
Member

Lukasa commented Feb 19, 2016

@the-efi Do you have pyopenssl, pyasn1, and ndg-httpsclient installed?

@the-efi
Copy link

the-efi commented Feb 19, 2016

pyopenssl: negative
pyasn1: pyasn1==0.1.8 (transient, I guess)
ndg-httpsclient: negative

@Lukasa
Copy link
Member

Lukasa commented Feb 19, 2016

Ok. You're also running Python 2.7, so you and the poster seem to be having different problems.

Do you know if you hit your problem during connection setup, or on a long-running connection?

@the-efi
Copy link

the-efi commented Feb 19, 2016

I would imagine this is during connection setup, but if requests reuses previously opened connections with Connection: keep-alive I might be wrong.

@Lukasa
Copy link
Member

Lukasa commented Feb 19, 2016

Requests does indeed re-use previously opened connections where possible, which is why I asked the question. ;)

It would be very useful if we could get a packet capture of this problem in your case, though that may be tricky given that it occurs under heavy load.

@the-efi
Copy link

the-efi commented Feb 19, 2016

No problem, I will see what I can do about it after the weekend. Would you like me to submit that as a new issue?

@Lukasa
Copy link
Member

Lukasa commented Feb 19, 2016

Yes please. =)

@caizixian
Copy link
Author

@Lukasa Any progress with urllib3?

@Lukasa
Copy link
Member

Lukasa commented Feb 20, 2016

@caizixian We're getting there, but we have some problems with our CI testing because Travis CI has a fairly old PyPy image that doesn't behave well with PyOpenSSL at the moment. I'll see if I can get this to work sometime this weekend.

@kennethreitz
Copy link
Contributor

@Lukasa @shazow urllib3 always has a home at http://ci.kennethreitz.org, if desired!

@Lukasa
Copy link
Member

Lukasa commented Jan 20, 2017

The error is unclear, but most likely it is a result of your OpenSSL version. Your claim that Ubuntu 14.04 has no OpenSSL simply cannot be true if you are making HTTPS requests. My best guess is that the server is sending EOF because none of your ciphers are acceptable. Ubuntu works because it has a newer OpenSSL with newer ciphers. Installing PyOpenSSL works because it provides a vendored copy of OpenSSL 1.0.2, also with newer ciphers.

@ghost
Copy link

ghost commented Feb 1, 2017

Hello!

I have a problem with some https-sites and request library.
Site: https://ndmc.gov.in/vacancy.aspx

installed:
appdirs==1.4.0
cffi==1.9.1
cryptography==1.7.2
idna==2.2
ndg-httpsclient==0.4.2
packaging==16.8
pyasn1==0.1.9
pycparser==2.17
pyOpenSSL==16.2.0
pyparsing==2.1.10
requests==2.13.0
six==1.10.0
urllib3==1.20
OpenSSL 1.0.2k 26 Jan 2017

get an error: requests.exceptions.SSLError: ("bad handshake: SysCallError(-1, 'Unexpected EOF')",)

OS: Archbang linux, latest
Python 3.6 & Python 2.7 - same error

@Lukasa
Copy link
Member

Lukasa commented Feb 2, 2017

You're another person who is winning our competition of who can attempt to contact the worst HTTPS server in the world. This server is awfully configured, it is entirely insecure. The reason you're encountering this problem is because Requests no longer supports any of the cipher suites this server supports because they're all either weak or insecure. In the first instance I recommend you attempt to pressure someone to fix the server, but if you really must contact it you can re-add 3DES like this.

@AlmogCohen
Copy link

@vyscond saved my life. Never mind what I did on my OSX, it went away only when installing pyopenssl ndg-httpsclient pyasn1 urllib3. Maybe it should be added as dependencies for OSX installation of requests?

@Lukasa
Copy link
Member

Lukasa commented Apr 15, 2017

It is only useful on some configurations of OS X and Python. The end result is that they remain optional.

@AlmogCohen
Copy link

I'm wondering how much time people spend before they (maybe) find the solution to that problem. I had to through a lot to find this thread and go through it. Is it worth it?

@Lukasa
Copy link
Member

Lukasa commented Apr 15, 2017

Depends. Problems can be introduced by requiring these dependencies too, not least that it adds a new OpenSSL to your system that is versioned and managed separately.

@natalie-o-perret
Copy link

@Lukasa for some reasons I got my setup working, seems pyopenssl (installed via requests[security] is messing up the certificates attached to some requests.
I had to uninstall the pyopenssl package in order to force requests to use OpenSSL in urllib3.
This happens when using adal (https://github.com/AzureAD/azure-activedirectory-library-for-python) which basically does not work with some old versions of requests (the ones supporting the certificates).
Seems a bit voodoo to me, though.

@akashagarwal19
Copy link

I was having this issue on Mac OSX Sierra v 10.12.0. Tried everything on this thread, didn't work. Finally upgraded my OS to v10.12.6 and the issue went away.

@komuw
Copy link

komuw commented Nov 14, 2017

The error may also manifest itself when using python-requests to make an api call to a site that is behind a vpn, and that vpn tunnel happens to be down at that moment.

@hussainakbar10p
Copy link

hussainakbar10p commented Feb 1, 2018

Hi guys!

I am a bit new to requests myself and found this error while doing a POC with Requests to see if it can fulfill my requirements for common criteria compliance. I tried to connect my Requests POC to this tool, I am specifically looking at the test cases for FIA-X509 Ext 1.1 but this is what i got:

Traceback (most recent call last):
File "/home/hussain/Desktop/pythonVenv/python36Venv/lib/python3.6/site-packages/urllib3/connectionpool.py", line 601, in urlopen
chunked=chunked)
File "/home/hussain/Desktop/pythonVenv/python36Venv/lib/python3.6/site-packages/urllib3/connectionpool.py", line 346, in _make_request
self._validate_conn(conn)
File "/home/hussain/Desktop/pythonVenv/python36Venv/lib/python3.6/site-packages/urllib3/connectionpool.py", line 850, in validate_conn
conn.connect()
File "/home/hussain/Desktop/pythonVenv/python36Venv/lib/python3.6/site-packages/urllib3/connection.py", line 326, in connect
ssl_context=context)
File "/home/hussain/Desktop/pythonVenv/python36Venv/lib/python3.6/site-packages/urllib3/util/ssl
.py", line 329, in ssl_wrap_socket
return context.wrap_socket(sock, server_hostname=server_hostname)
File "/usr/lib/python3.6/ssl.py", line 407, in wrap_socket
_context=self, _session=session)
File "/usr/lib/python3.6/ssl.py", line 814, in init
self.do_handshake()
File "/usr/lib/python3.6/ssl.py", line 1068, in do_handshake
self._sslobj.do_handshake()
File "/usr/lib/python3.6/ssl.py", line 689, in do_handshake
self._sslobj.do_handshake()
ssl.SSLEOFError: EOF occurred in violation of protocol (_ssl.c:777)

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
File "/home/hussain/Desktop/pythonVenv/python36Venv/lib/python3.6/site-packages/requests/adapters.py", line 440, in send
timeout=timeout
File "/home/hussain/Desktop/pythonVenv/python36Venv/lib/python3.6/site-packages/urllib3/connectionpool.py", line 639, in urlopen
_stacktrace=sys.exc_info()[2])
File "/home/hussain/Desktop/pythonVenv/python36Venv/lib/python3.6/site-packages/urllib3/util/retry.py", line 388, in increment
raise MaxRetryError(_pool, url, error or ResponseError(cause))
urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='10.0.0.221', port=443): Max retries exceeded with url: / (Caused by SSLError(SSLEOFError(8, 'EOF occurred in violation of protocol (_ssl.c:777)'),))

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
File "req.py", line 91, in
r = session.request('GET', 'https://10.0.0.221', verify=True)
File "/home/hussain/Desktop/pythonVenv/python36Venv/lib/python3.6/site-packages/requests/sessions.py", line 508, in request
resp = self.send(prep, **send_kwargs)
File "/home/hussain/Desktop/pythonVenv/python36Venv/lib/python3.6/site-packages/requests/sessions.py", line 618, in send
r = adapter.send(request, **kwargs)
File "/home/hussain/Desktop/pythonVenv/python36Venv/lib/python3.6/site-packages/requests/adapters.py", line 506, in send
raise SSLError(e, request=request)
requests.exceptions.SSLError: HTTPSConnectionPool(host='10.0.0.221', port=443): Max retries exceeded with url: / (Caused by SSLError(SSLEOFError(8, 'EOF occurred in violation of protocol (_ssl.c:777)'),))

this is the POC code that i am using:

import ssl
import requests

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

CIPHERS = (
    'RSA+AES'
)

class TlsAdapter(HTTPAdapter):
    def __init__(self, ssl_options=0, **kwargs):
        self.ssl_options = ssl_options
        super(TlsAdapter, self).__init__(**kwargs)

    def init_poolmanager(self, *pool_args, **pool_kwargs):
        ctx = ssl_.create_urllib3_context(ciphers=CIPHERS, cert_reqs=ssl.CERT_REQUIRED, options=self.ssl_options)

        self.poolmanager = PoolManager(*pool_args,
                                       ssl_context=ctx,
                                       **pool_kwargs)

session = requests.session()

adapter = TlsAdapter(ssl.OP_NO_TLSv1 | ssl.OP_NO_TLSv1_1)
session.mount("https://", adapter)
r = session.request('GET', 'https://10.0.0.221', verify=True)
print(r)

where 10.0.0.221 is the place where i have placed the tool for verification.

I am not exactly sure as to why this error is occurring. I tried going through this thread as well as multiple other questions on stackoverflow as well but could not find a suitable solution.

I will admit that i do not have a clear understanding of the TLS protocol as well at this point in time. So if someone could guide me as to what's the problem here, i'd be grateful.

Please let me know if i missed anything or need to provide any sort of additional information. Thanks!

@cgoodric
Copy link

Just as an FYI, this error also occurs when SSL isn't enabled on the server you're connecting to.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Sep 4, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests