跳到主要内容
ecdsa.com
Python ssl module (OpenSSL 3)Python cryptography 库

错误信息

[SSL: UNSAFE_LEGACY_RENEGOTIATION_DISABLED] unsafe legacy renegotiation disabled

出现在链接 OpenSSL 3.0 或更高版本的 Python 上(2022年以来的大多数 Python 构建版本);OpenSSL 1.1.1 仍允许连接这类服务器。后面跟着源代码位置,例如“(_ssl.c:1082)”。

Python ssl module (OpenSSL 3) — ssl.SSLError, SSL_R_UNSAFE_LEGACY_RENEGOTIATION_DISABLED

含义

服务器协商的是 TLS 1.2 或更早的版本,且不支持 RFC 5746 的安全重新协商扩展。OpenSSL 3 客户端默认拒绝这类服务器,因为旧式重新协商允许中间人把自己的数据拼接到客户端请求的前面(CVE-2009-3555)。Python 继承了这个默认设置,因此连接在握手期间失败。

原因

修复方法

  1. 1.

    确认服务器不支持安全重新协商

    对于这类服务器,openssl s_client 会报告“Secure Renegotiation IS NOT supported”。

    bash
    openssl s_client -connect legacy.example.com:443 -servername legacy.example.com </dev/null 2>/dev/null \
      | grep -i 'secure renegotiation'
    # "Secure Renegotiation IS NOT supported" confirms the server lacks RFC 5746
  2. 2.

    修复服务器

    更新服务器的 TLS 栈或固件,或者提供 TLS 1.3,就能为所有客户端消除这个问题。

    text
    Server / appliance owners: update the TLS stack or firmware to any release
    supporting RFC 5746 (every mainstream TLS library since 2010), or enable TLS 1.3,
    which has no renegotiation at all.
  3. 3.

    临时解决办法:只对一台主机放行

    ssl.OP_LEGACY_SERVER_CONNECT(Python 3.12+)只在这一个上下文中重新允许连接这类服务器。它会让该主机重新面临重新协商拼接风险,因此不要全局设置它,也不要通过系统的 OpenSSL 配置设置它。

    python
    # Temporary workaround for one legacy host only (Python 3.12+: ssl.OP_LEGACY_SERVER_CONNECT)
    import ssl, urllib.request
    
    ctx = ssl.create_default_context()
    ctx.options |= ssl.OP_LEGACY_SERVER_CONNECT
    urllib.request.urlopen("https://legacy.example.com/", context=ctx)

相关错误

浏览完整的签名错误库