Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Forcing requests library to use TLSv1.1 or TLSv1.2 in Python

Tags:

python

ssl

I am trying to send a POST call using requests library in python to a server. Earlier I was able to successfully send POST calls but recently, the server deprecated TLSv1.0 and now only supports TLSv1.1 and TLSv1.2. Now the same code throws me a "requests.exceptions.SSLError: EOF occurred in violation of protocol (_ssl.c:590)" error.

I found this thread on stackoverflow Python Requests requests.exceptions.SSLError: [Errno 8] _ssl.c:504: EOF occurred in violation of protocol which says that we need to subclass the HTTPAdapter after which the session object will use TLSv1. I changed my code accordingly and here is my new code

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
        )

url="https://mywebsite.com/ui/"
headers={"Cookie":"some_value","X-CSRF-Token":"some value","Content-Type":"application/json"}    
payload={"name":"some value","Id":"some value"}    
s = requests.Session()
s.mount('https://', MyAdapter())

r=s.post(url,json=payload,headers=headers)
html=r.text
print html

But even after using this, I get the same error EOF occurred in violation of protocol (_ssl.c:590).

My first question is that, I somewhere read that requests by default uses ssl. I know that my server used TLSv1.0 then, so was my code working because TLSv1.0 has backward compatibility with ssl3.0 ?

My second question is that, the stackoverflow thread that I mentioned above using which I changed my code to subclass HTTPAdapter, said that this will work for TLSv1. But since TLSv1.0 is deprecated in my server, will this code still work?

like image 963
Mr. Bing Avatar asked Jul 21 '16 10:07

Mr. Bing


2 Answers

The TLS stack will use the best version available automatically. If it does not work any longer when TLS 1.0 support is disabled at the server it usually means that your local TLS stack simply does not support newer protocol version like TLS 1.2. This is often the case on Mac OS X since it ships with a rotten old version of OpenSSL (0.9.8). In this case no python code will help you to work around the problem, but you need to get a python which uses a newer version of OpenSSL.

To check which openssl version you are using execute the following within python:

import ssl
print(ssl.OPENSSL_VERSION)

To have support for TLS 1.2 you need OpenSSL version 1.0.2 or 1.0.1. If you have only 1.0.0 or 0.9.8 you need to upgrade your python+OpenSSL. See Updating openssl in python 2.7 for more information on how to do this.

like image 152
Steffen Ullrich Avatar answered Sep 17 '22 15:09

Steffen Ullrich


I was getting random connection errors from very old server (it's rated F by https://www.ssllabs.com) until I wasn't start using this code in my HTTPAdapter:

def init_poolmanager(self, *args, **kwargs):
    ssl_context = ssl.create_default_context()

    # Sets up old and insecure TLSv1.
    ssl_context.options &= ~ssl.OP_NO_TLSv1_3 & ~ssl.OP_NO_TLSv1_2 & ~ssl.OP_NO_TLSv1_1
    ssl_context.minimum_version = ssl.TLSVersion.TLSv1

    # Also you could try to set ciphers manually as it was in my case.
    # On other ciphers their server was reset the connection with:
    # [Errno 104] Connection reset by peer
    # ssl_context.set_ciphers("ECDHE-RSA-AES256-SHA")

    # See urllib3.poolmanager.SSL_KEYWORDS for all available keys.
    kwargs["ssl_context"] = ssl_context

    return super().init_poolmanager(*args, **kwargs)
like image 30
frost-nzcr4 Avatar answered Sep 18 '22 15:09

frost-nzcr4