psf / requests

A simple, yet elegant, HTTP library.
https://requests.readthedocs.io/en/latest/
Apache License 2.0
52.07k stars 9.31k forks source link

TLS SNI Support (Under Python 2.7.6) #5751

Closed Tectract closed 3 years ago

Tectract commented 3 years ago

Hello.

In reference to https://github.com/psf/requests/issues/749

I'm trying to get SNI support working on a system that is locked to Python2.7.6 / pip20.3.4.

I've tried 'pip install -U requests' and 'pip install -U requests[security]', but the issue is not resolved for me.

I'm getting this error when I try to connect to servers that support SNI:

[Errno 1] _ssl.c:510: error:14077410:SSL routines:SSL23_GET_SERVER_HELLO:sslv3 alert handshake failure

Is there some way I can still backport SNI support into my Python2.7.6 / pip installation here? Could I just copy the SSL libs from a pip3 installation or something?

Tectract commented 3 years ago

Was the code from PR 749 reverted? I'm looking at the init.py from requests v2.25.1 and I don't see this:

# Attempt to enable urllib3's SNI support, if possible
try:
    from requests.packages.urllib3.contrib import pyopenssl
    pyopenssl.inject_into_urllib3()
except ImportError:
    pass
sethmlarson commented 3 years ago

2.24.0 dropped the automatic usage of pyOpenSSL if SNI support is detected. What is the result of ssl.HAS_SNI for your distribution (should be False)? In that can pyOpenSSL should be getting injected automatically.

Tectract commented 3 years ago

This is interesting. Any help is greatly, greatly appreciated here. Thanks!

>>> import ssl
>>> ssl.HAS_SNI
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'module' object has no attribute 'HAS_SNI'
Tectract commented 3 years ago

I tried going down to requests 2.23.0, and now I see code trying to interact with urrlib3 in the init, but sadly still no dice, same error for me. Are there maybe specific versions of urllib3/pyopenssl I can try, or some other way to test or patch the ssl / nmi connections?

Tectract commented 3 years ago

Hmmmmmm, I tried using a different tool... this is a problem connecting the coinbase websockets so I tried a python coinbase tool. It definitely looks like it might be something with the ssl.py file in my /usr/lib/python2.7/ folder, which is a system folder as I understand. Can I get it to use a different ssl implementation somehow?

Here's what I see now, this might be helpful:

Traceback (most recent call last):
  File "/usr/lib/python2.7/threading.py", line 810, in __bootstrap_inner
    self.run()
  File "/usr/lib/python2.7/threading.py", line 763, in run
    self.__target(*self.__args, **self.__kwargs)
  File "/home/myusername/.local/lib/python2.7/site-packages/cbpro/websocket_client.py", line 40, in _go
    self._connect()
  File "/home/myusername/.local/lib/python2.7/site-packages/cbpro/websocket_client.py", line 72, in _connect
    self.ws = create_connection(self.url)
  File "/usr/local/lib/python2.7/dist-packages/websocket/_core.py", line 487, in create_connection
    websock.connect(url, **options)
  File "/usr/local/lib/python2.7/dist-packages/websocket/_core.py", line 211, in connect
    options.pop('socket', None))
  File "/usr/local/lib/python2.7/dist-packages/websocket/_http.py", line 77, in connect
    sock = _ssl_socket(sock, options.sslopt, hostname)
  File "/usr/local/lib/python2.7/dist-packages/websocket/_http.py", line 182, in _ssl_socket
    sock = ssl.wrap_socket(sock, **sslopt)
  File "/usr/lib/python2.7/ssl.py", line 487, in wrap_socket
    ciphers=ciphers)
  File "/usr/lib/python2.7/ssl.py", line 243, in __init__
    self.do_handshake()
  File "/usr/lib/python2.7/ssl.py", line 405, in do_handshake
    self._sslobj.do_handshake()
SSLError: [Errno 1] _ssl.c:510: error:14077410:SSL routines:SSL23_GET_SERVER_HELLO:sslv3 alert handshake failure
nateprewitt commented 3 years ago

Hi @Tectract, I don't believe there's an alternative option. If injecting the pyopenssl module from urllib3.contrib module manually isn't resolving the issue, I'm not sure there's much we can do. It would appear there's perhaps a distro modified version of ssl.py on your machine, or another environment issue. This issue tracker won't be able to help with that unfortunately.

I'm going to resolve this for now, let us know if you've have more information on what you think is a defect in Requests.

Tectract commented 3 years ago

Hello, I did eventually find a way to get TLS SNI support under Python 2.7.

From my notes:

python requests package 2.24.0 dropped the automatic usage of pyOpenSSL if SNI support is detected
might work with an older urllib3 (?)

from requests/__init__.py

# Attempt to enable urllib3's SNI support, if possible
try:
  from urllib3.contrib import pyopenssl
  pyopenssl.inject_into_urllib3()

within your python code, where you see this:

  self.sock = ssl.wrap_socket(self.sock)

change it to this:

  self.ssl_options = { "server_hostname" : self.host }
  self.sock = ssl.SSLSocket(self.sock, **self.ssl_options)

Thank you for your support!