SSL 错误不安全旧版重新协商已禁用

Gia*_*ilo 72 python ssl openssl runtime-error

我正在运行一个 Python 代码,我必须从HTTPSConnectionPool(host='ssd.jpl.nasa.gov', port=443). 但每次我尝试运行代码时都会收到以下错误。我的系统是 MAC 操作系统 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)')))
Run Code Online (Sandbox Code Playgroud)

我真的不知道如何绕过这个问题。

小智 125

警告:启用旧版不安全重新协商时,SSL 连接将容易受到中间人前缀攻击,如CVE-2009-3555中所述。

在https://bugs.launchpad.net/bugs/1963834https://bugs.launchpad.net/ubuntu/+source/gnutls28/+bug/1856428的帮助下

请注意,不建议编辑系统的 openssl.conf,因为一旦更新 openssl,您可能会丢失所做的更改。

openssl.cnf在任何目录中创建一个包含以下内容的自定义文件:

openssl_conf = openssl_init

[openssl_init]
ssl_conf = ssl_sect

[ssl_sect]
system_default = system_default_sect

[system_default_sect]
Options = UnsafeLegacyRenegotiation
Run Code Online (Sandbox Code Playgroud)

在运行程序之前,请确保在运行 scraper 时OPENSSL_CONF将环境变量设置为自定义完整路径,如下所示:openssl.cnf

OPENSSL_CONF=/path/to/custom/openssl.cnf python your_scraper.py
Run Code Online (Sandbox Code Playgroud)

或者像这样:

export OPENSSL_CONF=/path/to/custom/openssl.cnf
python your_scraper.py
Run Code Online (Sandbox Code Playgroud)

或者,如果您使用 pipelinenv 或 systemd 或 docker,请将其放入您的.env文件中

OPENSSL_CONF=/path/to/custom/openssl.cnf
Run Code Online (Sandbox Code Playgroud)

  • 这对我也有用,尽管我并不完全明白我在做什么。(只是想获取 TD ameritrade 股票。在升级到 22.04 之前正在工作)要编辑的文件是“修改现有的 openssl 配置文件,路径:/usr/lib/ssl/openssl.cnf” (2认同)

ahm*_*ara 48

Harry Mallon的答案的完整代码片段:

定义一个重用的方法:

import requests
import urllib3
import ssl


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)


def get_legacy_session():
    ctx = ssl.create_default_context(ssl.Purpose.SERVER_AUTH)
    ctx.options |= 0x4  # OP_LEGACY_SERVER_CONNECT
    session = requests.session()
    session.mount('https://', CustomHttpAdapter(ctx))
    return session
Run Code Online (Sandbox Code Playgroud)

然后用它代替请求调用:

get_legacy_session().get("some-url")
Run Code Online (Sandbox Code Playgroud)

  • 好的!我现在简单地使用了 `with (get_legacy_session() as s, s.get("some-url") as response)` 并且它有效。对于在谷歌云中部署非常有用(因为我无法在这里降级 SSL) (2认同)

Har*_*lon 34

我在 Linux 上遇到了同样的错误(当服务器不支持“RFC 5746 安全重新协商”并且客户端使用 OpenSSL 3(默认情况下强制执行该标准)时,就会发生这种情况)。

这是一个解决方案(您可能需要稍微调整一下)。

  1. 在您的 Python 代码中导入sslandurllib3
  2. 创建一个使用自定义的 HttpAdapterssl 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)
Run Code Online (Sandbox Code Playgroud)
  1. 设置ssl启用 的上下文OP_LEGACY_SERVER_CONNECT,并将其与您的自定义适配器一起使用。

ssl.OP_LEGACY_SERVER_CONNECT在 Python 中尚不可用(https://bugs.python.org/issue44888)。然而事实证明,在 OpenSSL 中,其位字段值为 0x4。所以我们可以做以下事情。

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

  • 这可行,问题是:如果我使用此解决方案,我是否容易受到 CVE-2009-3555 中所述的中间人前缀攻击? (3认同)
  • `session` 是 `requests.Session()` 的一个实例。我的代码片段不完整,因为它们取自一个更大的项目。您必须调整它们以适合您的代码。 (2认同)
  • 这会导致: ValueError: 当启用 check_hostname 时,无法将 verify_mode 设置为 CERT_NONE。只需添加,那么它应该正在运行 >>> ctx.check_hostname = False >>> ctx.verify_mode = ssl.CERT_NONE (2认同)

Jer*_*unt 16

当使用 OpenSSL 3 连接到不支持它的服务器时,会出现此错误。解决办法是降级python中的加密包:

pip install cryptography==36.0.2在使用的环境中运行。

来源: https: //github.com/scrapy/scrapy/issues/5491

编辑:请参阅 Harry Mallon 和 ahmkara 的答案,以获取无需降级密码学的修复程序

  • 在 ubuntu 22.04 上尝试使用 python3.8、3.9、3.10 - 没有运气 (9认同)
  • 对我和“api.searchads.apple.com”不起作用 (7认同)
  • 我通过加密 37.0.2 对 python 请求 2.28.1 遇到了同样的问题。我将加密技术降级到 36.0.2 并解决了问题。tnx很多:X (2认同)

Mic*_*ner 6

如果你想使用 urlopen,这个片段对我有用。

import ssl
import urllib.request

url = 'http://....'

# Set up SSL context to allow legacy TLS versions
ctx = ssl.create_default_context(ssl.Purpose.SERVER_AUTH)
ctx.options |= 0x4  # OP_LEGACY_SERVER_CONNECT

# Use urllib to open the URL and read the content
response = urllib.request.urlopen(url, context=ctx)
Run Code Online (Sandbox Code Playgroud)


bus*_*oni 5

这并不能真正解决问题,但一位同事从节点 18 切换到节点 16 并且不再收到此错误。