Reputation: 2531
Trying to make a simple get request using Requests session but I keep getting SSLerror for a specific site. I think maybe the problem is with the site (I did a scan using https://www.ssllabs.com, results are down bellow), but I cant be sure because I have no knowledge in this area :) I would sure like to understand what is going on.
A solution/explanation would be great, thanks!
The code:
import requests
requests.get('https://www.reporo.com/')
I'm getting the next error:
SSLError: [Errno bad handshake] [('SSL routines', 'SSL3_GET_SERVER_CERTIFICATE', 'certificate verify failed')]
---------------------------------------------------------------------------
SSLError Traceback (most recent call last)
<ipython-input-7-cfc21b287fee> in <module>()
----> 1 requests.get('https://www.reporo.com/')
/usr/local/lib/python2.7/dist-packages/requests/api.pyc in get(url, **kwargs)
63
64 kwargs.setdefault('allow_redirects', True)
---> 65 return request('get', url, **kwargs)
66
67
/usr/local/lib/python2.7/dist-packages/requests/api.pyc in request(method, url, **kwargs)
47
48 session = sessions.Session()
---> 49 response = session.request(method=method, url=url, **kwargs)
50 # By explicitly closing the session, we avoid leaving sockets open which
51 # can trigger a ResourceWarning in some cases, and look like a memory leak
/usr/local/lib/python2.7/dist-packages/requests/sessions.pyc in request(self, method, url, params, data, headers, cookies, files, auth, timeout, allow_redirects, proxies, hooks, stream, verify, cert, json)
459 }
460 send_kwargs.update(settings)
--> 461 resp = self.send(prep, **send_kwargs)
462
463 return resp
/usr/local/lib/python2.7/dist-packages/requests/sessions.pyc in send(self, request, **kwargs)
571
572 # Send the request
--> 573 r = adapter.send(request, **kwargs)
574
575 # Total elapsed time of the request (approximately)
/usr/local/lib/python2.7/dist-packages/requests/adapters.pyc in send(self, request, stream, timeout, verify, cert, proxies)
429 except (_SSLError, _HTTPError) as e:
430 if isinstance(e, _SSLError):
--> 431 raise SSLError(e, request=request)
432 elif isinstance(e, ReadTimeoutError):
433 raise ReadTimeout(e, request=request)
SSLError: [Errno bad handshake] [('SSL routines', 'SSL3_GET_SERVER_CERTIFICATE', 'certificate verify failed')]
I ran a scan at https://www.ssllabs.com and got the following:
SSL Report: reporo.com
Assessed on: Sun Feb 22 21:42:57 PST 2015 | Clear cache Scan Another >>
Server Domain(s) Test time Grade
1 154.51.128.13
Certificate not valid for domain name
reporo.com
Sun Feb 22 21:40:53 PST 2015
Duration: 9.167 sec -
2 198.12.15.168
protected.ddosdefend.com
Ready
www.reporo.com
Sun Feb 22 21:41:02 PST 2015
Duration: 115.189 sec
F
Upvotes: 24
Views: 63590
Reputation: 5405
This error also occur when using MimT.
You can trust your CA by using requests.get('https://github.com', verify='/path/to/certfile')
, or set its path to REQUESTS_CA_BUNDLE
environment variable.
Ref: https://docs.python-requests.org/en/master/user/advanced/#ssl-cert-verification
Upvotes: 0
Reputation: 99
Steffen Ullrich has the best answer for when it is the case that a website has valid certs as determined by the browser but the complete certification chain is not supplied by the server.
Sometimes just the root or intermediate cert is missing and browsers are equipped to download or verify the missing cert on the fly, but with the requests module you will have verify it manually. I used SSL labs to determine the full certificate chain as a .pem file. Enter the url to the website of interest, and wait for the test to complete. Then navigate to and expand "certification paths". There may be multiple trusted paths (or none, in which case the eventual request will not succeed), and off to the right you will see a download chain button.
Copy the full chain as text and save it as a .pem file. Then you pass the path of this .pem file to the requests function when you make a request:
r = requests.get(url, verify= "path/to/chain.pem")
Upvotes: 1
Reputation: 14632
Ran into similar issue and fixed by following:
pip install -U requests[security]
Upvotes: 3
Reputation: 27
I had the same error. Downgrading requests from requests-2.17.3 to requests-2.11.0 solved it for me.
pip uninstall requests
pip install requests==2.11.0
Upvotes: 1
Reputation: 123260
The certificate itself for www.reporo.com (not reporo.com) is valid, but it is missing a chain certificate as shown in the report by ssllabs:
Chain issues Incomplete
....
2 Extra download Thawte DV SSL CA
Fingerprint: 3ca958f3e7d6837e1c1acf8b0f6a2e6d487d6762
The "Incomplete" and "Extra download" are the major points. Some browsers will have the missing chain certificate cached, others will do the download and other will fail. If you try the site with a fresh Firefox profile (which does not have any certificates cached) it will fail too.
You could download the missing chain certificates and use it as trusted CA certificate with the verify
parameter for requests. Don't just disable validation because then you are open to man-in-the-middle attacks.
Step by step instruction:
chain.pem
. Make sure that each of the files did end with a valid end of line character (which they do not as downloaded). The resulting file should look like this.Modify your call to
requests.get('https://www.reporo.com/', verify = 'chain.pem')
Upvotes: 25
Reputation: 221
You can disable certificate verification:
requests.get('https://www.reporo.com/', verify=False)
but without certificate verification there is no man-in-the-middle attack protection.
Upvotes: 17