I need to get data from a URL that has some certificate problems. It works with curl -k
(that skips verification). So I tried with verify=False
in python requests
but I'm still getting [SSL: SSLV3_ALERT_HANDSHAKE_FAILURE]. Any idea how to bypass this?
I'm using python 3.10.12 and requests 2.32.3 Here goes a code for testing purposes:
import os
import requests
# curl fails
teste = os.system("curl -o capabilities.xml 'https://geoserver.car.gov.br/geoserver/ows?service=WMS&version=1.3.0&request=GetCapabilities'")
# ignoring verification -k works
teste = os.system("curl -k -o capabilities.xml 'https://geoserver.car.gov.br/geoserver/ows?service=WMS&version=1.3.0&request=GetCapabilities'")
# Trying with python
url = "https://geoserver.car.gov.br/geoserver/ows"
params = {
'service':'WMS',
'version':'1.3.0',
'request':'GetCapabilities'
}
# this fails with certificate error
teste = requests.get(url, params)
# verify = False does not do the trick
teste = requests.get(url, params, verify=False)
Update:
It appears as though the site uses only TLS1.2 for cypher suit and python requests does not like that. Any way to have python use that Cypher?
The problem is not the TLS version, TLS 1.2 is still allowed by default in current Python. The problem is instead that the server only supports weak ciphers which require the obsolete RSA key exchange (i.e. no forward secrecy). To allow this you need to adjust the security level:
import requests
import ssl
from requests.adapters import HTTPAdapter
class CustomSSLAdapter(HTTPAdapter):
def init_poolmanager(self, *args, **kwargs):
ssl_context = ssl.create_default_context()
ssl_context.set_ciphers('DEFAULT@SECLEVEL=0')
ssl_context.check_hostname = False
kwargs["ssl_context"] = ssl_context
return super().init_poolmanager(*args, **kwargs)
sess = requests.Session()
sess.mount('https://', CustomSSLAdapter())
url = 'https://geoserver.car.gov.br/geoserver/ows?service=WMS&version=1.3.0&request=GetCapabilities'
resp = sess.get(url, verify=False)
print(resp)