67

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?

4
  • I edited Lukasa answer (the correct one) for a workaround to have SNI support in older requests in case you can't use the latest github version. Please ensure you have the required dependencies (not only the python ones, also openssl) installed in your system. It will be available once the edit is reviewed :) Commented Sep 4, 2013 at 1:25
  • I think it's better creating a new answer rather than perform a redical edit in the post of someone Commented Sep 4, 2013 at 1:27
  • Well his answer is correct so I thought it wasn't nice to have another answer for another case, personally I really prefer one answer having all the info. But I'll post another answer then. Commented Sep 4, 2013 at 16:00
  • Curious, what operating system were you using to test this? Hitting SNI hosts works for me with Ubuntu Precise but not Lucid, and I cannot figure out why. stackoverflow.com/questions/24522757/… Commented Jul 2, 2014 at 4:17

7 Answers 7

133

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:

Sign up to request clarification or add additional context in comments.

8 Comments

Thank you. I also saw this pull request github.com/kennethreitz/requests/pull/1347 which together with installing urllib3, ndg-httpsclient and pyasn1 solved it.
Is this fix still working? I get [Errno bad handshake] [('SSL routines', 'SSL3_GET_SERVER_CERTIFICATE', 'certificate verify failed')].
This fix absolutely is still working. Looks like the certificate isn't valid.
Just so you know, your answer is referenced in this FAQ - at the end of the page.
Installing requests (2.18) also installs idna. So only pyopenssl package not installed as a dependency but required for SNI.
|
22

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

3 Comments

I also had to install: yum install python-devel before going to the pip installs..
Actually, for me, ndg-httpsclient installed all of those python packages except urllib3. Note to get a recent version of pip, though, or it won't work any how..
@ihue These installations were needed years ago to get around the fact that the Python SSL module in the standard library didn't support SNI. That's no longer the case, and using the newest versions of Python 2 or 3 don't require these extra installs.
13

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

pip install requests[security]

1 Comment

Beware, this now needs setuptools-rust, and rust support.
5

@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

Comments

5

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/

1 Comment

I kept getting requests.exceptions.SSLError: [SSL: SSLV3_ALERT_HANDSHAKE_FAILURE] sslv3 alert handshake failure (_ssl.c:590) and I have Python 2.7.10
2

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.

Comments

-1

I was getting this error all the time...

ssl.SSLError: [SSL: SSLV3_ALERT_HANDSHAKE_FAILURE] sslv3 alert handshake failure (_ssl.c:1006)

With using python 3.11.5 and requests 2.31.0. After downgrading requests lib to 2.28.2 everything worked as expected when used verify=False.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.