Python3 SSL握手失败求助:SSLV3_ALERT_HANDSHAKE_FAILURE
SSL握手失败(SSLV3_ALERT_HANDSHAKE_FAILURE)排查与解决
问题重现
尝试实现SSL握手并提取服务器证书的SubjectName/CommonName时,触发如下错误:
File "/usr/lib/python3.10/ssl.py", line 1342, in do_handshake self._sslobj.do_handshake() ssl.SSLError: [SSL: SSLV3_ALERT_HANDSHAKE_FAILURE] sslv3 alert handshake failure (_ssl.c:997)
已尝试的解决方案(均无效)
- 猴子补丁跳过证书验证:
ssl._create_default_https_context = ssl._create_unverified_context - 禁用SSL上下文的主机名检查与证书验证:
sslContext.check_hostname = False sslContext.verify_mode = ssl.CERT_NONE - 使用自定义加密套件(字符串存在截断错误):
cipher = (':ECDHE-RSA-AES128-GCM-SHA256:DES-CBC3-SHA:AES256-SHA:AES128-SHA:AES128-SHA256:AES256-GCM-SHA384:AES256-SHA256:ECDHE-RSA-DES-CBC3:EDH-RSA-DES-CBC3:EECDH+AESGCM:EDH-RSA-DES-CBC3-SHA:EDH-AESGCM:AES256+EECDH:ECHDE-RSA-AES256-GCM-SHA384:ECHDE-ECDSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECHDE-ECDSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:AES256+EDH:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-A$:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:HIGH:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!3DES:!MD5:!PSK') sslContext.set_ciphers(cipher) - 配置OpenSSL允许旧版重协商(未通过环境变量生效):
[openssl_init] ssl_conf = ssl_sect [ssl_sect] system_default = system_default_sect [system_default_sect] Options = UnsafeLegacyRenegotiation
测试脚本
import socket import ssl import time cipher = (':ECDHE-RSA-AES128-GCM-SHA256:DES-CBC3-SHA:AES256-SHA:AES128-SHA:AES128-SHA256:AES256-GCM-SHA384:AES256-SHA256:ECDHE-RSA-DES-CBC3:EDH-RSA-DES-CBC3:EECDH+AESGCM:EDH-RSA-DES-CBC3-SHA:EDH-AESGCM:AES256+EECDH:ECHDE-RSA-AES256-GCM-SHA384:ECHDE-ECDSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECHDE-ECDSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:AES256+EDH:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-A$:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:HIGH:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!3DES:!MD5:!PSK') ssl._create_default_https_context = ssl._create_unverified_context sslContext = ssl.create_default_context() sslContext.check_hostname = False sslContext.set_ciphers(cipher) sslContext.verify_mode = ssl.CERT_NONE clientSocket = socket.socket() secureClientSocket = sslContext.wrap_socket(clientSocket, do_handshake_on_connect=False) t1 = time.time() retval = secureClientSocket.connect(("example.com", 443)) print("Time taken to establish the connection:%2.3f"%(time.time() - t1)) t3 = time.time() secureClientSocket.do_handshake() print("Time taken for SSL handshake:%2.3f"%(time.time() - t3)) serverCertificate = secureClientSocket.getpeercert() print("Certificate obtained from the server:") print(serverCertificate)
环境配置
openssl version OpenSSL 3.0.7 1 Nov 2022 (Library: OpenSSL 3.0.7 1 Nov 2022) python3 --version Python 3.10.8
解决建议
修复加密套件字符串错误
你的自定义加密套件字符串中存在截断:DHE-RSA-A$,这会导致OpenSSL无法解析合法的套件列表,直接引发握手失败。删除该错误片段,或直接使用默认加密套件测试(注释掉sslContext.set_ciphers(cipher))。移除无效的猴子补丁
ssl._create_default_https_context仅作用于urllib.request等高层库的默认上下文,你手动创建的sslContext不受其影响,删除该行避免干扰。简化上下文配置
先使用最简化的配置确认基础握手是否正常:sslContext = ssl.create_default_context() sslContext.check_hostname = False sslContext.verify_mode = ssl.CERT_NONE # 不要设置自定义cipher,先使用默认值验证服务器SSL兼容性
用OpenSSL命令行测试目标服务器的支持协议与套件:openssl s_client -connect example.com:443查看输出中的
Cipher Suite和Protocol,确保客户端使用的协议/套件在服务器支持列表内。正确加载OpenSSL配置(若需)
若确实需要启用UnsafeLegacyRenegotiation,需将配置保存为文件(如openssl.cnf),然后通过环境变量指定:export OPENSSL_CONF=/path/to/openssl.cnf再运行Python脚本。
内容的提问来源于stack exchange,提问作者MC874
相关产品推荐
相关产品推荐

