using requests with TLS doesn't give SNI support

Question:

I’m using requests to communicate with a django app but

When I try

requests.get('https://mysite.com', verify=True)

I get the error:

hostname ‘mysite.com’ doesn’t match either of ‘*.myhost.com’, ‘myhost.com’

However, when I look at the browser, or http://www.digicert.com/help/ the certificate looks fine and dandy.

My host suggested it was the lack of SNI support from requests (and Github seems to confirm that https://github.com/kennethreitz/requests/issues/749 ). Has anyone found a work-around using requests?

Asked By: Massagran

||

Answers:

The current version of Requests should be just fine with SNI. Further down the GitHub issue you can see the requirements:

Try installing those packages and then give it another shot.

EDIT: As of Requests v2.12.1, ndg-httpsclient and pyasn1 are no longer required. The full list of required packages is now:

Answered By: Lukasa

@Lukasa answer is correct with the present (from github) requests. Remember to add OpenSSL in your system too apart from the pip dependencies he mentions.

If for deployment reasons you prefer a stable requests version like the 1.2.3 in pip, you can monkey patch that one to work with SNI like this:

import requests


def fileno(self):
    return self.socket.fileno()


def close(self):
    return self.connection.shutdown()


requests.pyopenssl.WrappedSocket.close = close
requests.pyopenssl.WrappedSocket.fileno = fileno
Answered By: AntonioMO

In order for me to get the accepted answer to work, I had to install a bunch of other packages, in this order:

  • yum install libffi-devel
  • yum install gcc
  • yum install openssl-devel
  • pip install urllib3
  • pip install pyopenssl
  • pip install ndg-httpsclient
  • pip install pyasn1
Answered By: Shane N

Or you can just use Python 2.7.9 and up:

“The entirety of Python 3.4’s ssl module has been backported for Python 2.7.9. See PEP 466 for justification.”

https://www.python.org/downloads/release/python-279/

Answered By: stantonk

Install requests module like this. This will install the security package extras.

pip install requests[security]

Answered By: Nandeesh

Copy my answer from Accessing https sites with IP address

On MAC High Sierra and Python 3.6.4, I tried the solution: requests toolbelt:HostHeaderSSLAdapter 1st, unfortunately, it doesn’t work for me, then I tried
forcediphttpsadapter, got it works finally.

The author explains everything in the readme part and has provided a sample script and it can be followed easily.

1.Install the library by pip install requests[security] forcediphttpsadapter

2.run the sample script:

import requests
from forcediphttpsadapter.adapters import ForcedIPHTTPSAdapter
session = requests.Session()
session.mount("https://example.com", ForcedIPHTTPSAdapter(dest_ip='1.2.3.4'))
response = session.get(
    '/some/path', headers={'Host': 'example.com'}, verify=False)

Note: For some cases, you may need to remove the prefix: ‘www’ from the url.

Answered By: Xb74Dkjb