'SSL error unsafe legacy renegotiation disabled

I am running a Python code where I have to get some data from HTTPSConnectionPool(host='ssd.jpl.nasa.gov', port=443). But every time I try to run the code I get the following error. I am on MAC OS 12.1

raise SSLError(e, request=request)
requests.exceptions.SSLError: HTTPSConnectionPool(host='ssd.jpl.nasa.gov', port=443): Max retries exceeded with url: /api/horizons.api?format=text&EPHEM_TYPE=OBSERVER&QUANTITIES_[...]_ (Caused by SSLError(SSLError(1, '[SSL: UNSAFE_LEGACY_RENEGOTIATION_DISABLED] unsafe legacy renegotiation disabled (_ssl.c:997)')))

I really don't know how to bypass this issue.. thank you for the help!



Solution 1:[1]

With the help of https://bugs.launchpad.net/bugs/1963834 and https://bugs.launchpad.net/ubuntu/+source/gnutls28/+bug/1856428

Beware that editing your system's openssl.conf is not recommended, because you might lose your changes once openssl is updated.

Create a custom openssl.cnf file in any directory with these contents:

openssl_conf = openssl_init

[openssl_init]
ssl_conf = ssl_sect

[ssl_sect]
system_default = system_default_sect

[system_default_sect]
Options = UnsafeLegacyRenegotiation

Before running your program, make sure your OPENSSL_CONF environment variable is set to your custom openssl.cnf full path when running the scraper like so:

OPENSSL_CONF=/path/to/custom/openssl.cnf python your_scraper.py

or like so:

export OPENSSL_CONF=/path/to/custom/openssl.cnf
python your_scraper.py

or, if you are using pipenv or systemd or docker, place this into your .env file

OPENSSL_CONF=/path/to/custom/openssl.cnf

Solution 2:[2]

I hit the same error on Linux (it happens when the server doesn't support "RFC 5746 secure renegotiation" and the client is using OpenSSL 3, which enforces that standard by default).

Here is a solution (you may have to adjust it slightly).

  1. Import ssl and urllib3 in your Python code
  2. Create a custom HttpAdapter which uses a custom ssl Context
class CustomHttpAdapter (requests.adapters.HTTPAdapter):
    '''Transport adapter" that allows us to use custom ssl_context.'''

    def __init__(self, ssl_context=None, **kwargs):
        self.ssl_context = ssl_context
        super().__init__(**kwargs)

    def init_poolmanager(self, connections, maxsize, block=False):
        self.poolmanager = urllib3.poolmanager.PoolManager(
            num_pools=connections, maxsize=maxsize,
            block=block, ssl_context=self.ssl_context)
  1. Set up an ssl context which enables OP_LEGACY_SERVER_CONNECT, and use it with your custom adapter.

ssl.OP_LEGACY_SERVER_CONNECT is not available in Python yet (https://bugs.python.org/issue44888). However it turns out that in OpenSSL its value is 0x4 in the bitfield. So we can do the following.

ctx = ssl.create_default_context(ssl.Purpose.SERVER_AUTH)
ctx.options |= 0x4
session.mount('https://', CustomHttpAdapter(ctx))

Solution 3:[3]

Seems to be a problem with a newer version of cryptography. Downgrading solved the problem for me.

pip install cryptography==36.0.2 in the used enviroment.

source: https://github.com/scrapy/scrapy/issues/5491

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 nurettin
Solution 2 Harry Mallon
Solution 3 Jeroen Vermunt