ssl.SSLError: [SSL: SSLV3_ALERT_HANDSHAKE_FAILURE] 错误处理

Python升级后poplib收邮件脚本问题解决
将Python从3.9.5升级到3.11.1后,原poplib收取邮件的脚本运行失败。查看文档发现是3.10版SSL相关版本变化所致。为适配新版SSL与原服务器,进行设置调整。之后又遇自签证书错误,借鉴爬虫忽略网站证书的方法解决问题,使脚本在新Python版本下恢复正常。

从python3.9.5升级到3.11.1 原来用poplib收取邮件的脚本运行失败:


    server = poplib.POP3_SSL(pop3_server, 995)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "c:\Python311-32\Lib\poplib.py", line 452, in __init__
    POP3.__init__(self, host, port, timeout)
  File "c:\Python311-32\Lib\poplib.py", line 104, in __init__
    self.sock = self._create_socket(timeout)
                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "c:\Python311-32\Lib\poplib.py", line 456, in _create_socket
    sock = self.context.wrap_socket(sock,
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "c:\Python311-32\Lib\ssl.py", line 517, in wrap_socket
    return self.sslsocket_class._create(
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "c:\Python311-32\Lib\ssl.py", line 1075, in _create
    self.do_handshake()
  File "c:\Python311-32\Lib\ssl.py", line 1346, in do_handshake
    self._sslobj.do_handshake()
ssl.SSLError: [SSL: SSLV3_ALERT_HANDSHAKE_FAILURE] sslv3 alert handshake failure (_ssl.c:992)

查看python升级变化的文档,提示在3.10版有涉及:

Important deprecations, removals or restrictions:

PEP 644, Require OpenSSL 1.1.1 or newer

应该是ssl相关的版本变化引起。

为使新版的SSL与原服务器的适配,增加设置:

import ssl
ctx = ssl.create_default_context()
ctx.set_ciphers('DEFAULT')
#...
server = poplib.POP3_SSL(pop3_server, 995,context=ctx)

运行发现已经能进一步了,但是又报错误:

    server = poplib.POP3_SSL(pop3_server, 995,context=ctx)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\python311-32\Lib\poplib.py", line 452, in __init__
    POP3.__init__(self, host, port, timeout)
  File "C:\python311-32\Lib\poplib.py", line 104, in __init__
    self.sock = self._create_socket(timeout)
                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\python311-32\Lib\poplib.py", line 456, in _create_socket
    sock = self.context.wrap_socket(sock,
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\python311-32\Lib\ssl.py", line 517, in wrap_socket
    return self.sslsocket_class._create(
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\python311-32\Lib\ssl.py", line 1075, in _create
    self.do_handshake()
  File "C:\python311-32\Lib\ssl.py", line 1346, in do_handshake
    self._sslobj.do_handshake()
ssl.SSLCertVerificationError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: self signed certificate in certificate chain (_ssl.c:992)

此为自签证书错误,借处理爬虫时,忽略网站证书的方法,查找对应功能调整为:

import ssl
ctx = ssl._create_unverified_context() #起到忽略证书校验的作用
ctx.set_ciphers('DEFAULT') #与老服务器握手搭配
#...
server = poplib.POP3_SSL(pop3_server, 995,context=ctx)

至此,在新python3.11版本下恢复正常,问题解决。

在使用 BoringSSL 库时,如果遇到错误 `error:10000410:SSL routines:OPENSSL_internal:SSLV3_ALERT_HANDSHAKE_FAILURE`,这通常表示客户端与服务器在 SSL/TLS 握手过程中未能成功协商通信参数,导致连接失败。此类错误可能由多种原因引起,包括但不限于协议版本不兼容、加密套件不匹配、证书验证失败等。 ### 原因分析 1. **TLS/SSL 协议版本不兼容** 客户端与服务器支持的 TLS/SSL 协议版本不一致可能导致握手失败。例如,客户端仅支持 TLS 1.0,而服务器要求 TLS 1.2 或更高版本。 2. **加密套件不匹配** 加密套件决定了客户端和服务器在建立安全连接时使用的加密算法。如果双方没有共同支持的加密套件,握手将失败。 3. **证书验证失败** 客户端无法验证服务器提供的证书,可能由于证书链不完整、证书过期、证书不受信任(未由受信任的 CA 签发)或证书域名不匹配等原因。 4. **服务器配置问题** 服务器端可能配置不当,例如未正确配置 TLS 参数、未启用必要的加密套件或证书配置错误。 ### 解决方案 1. **检查并更新协议版本** 确保客户端支持现代 TLS 协议版本(如 TLS 1.2 或 TLS 1.3)。对于使用 Python 的场景,可以通过设置 SSL 上下文来指定最低协议版本: ```python import ssl context = ssl.SSLContext(ssl.PROTOCOL_TLSv1_2) ``` 2. **设置默认加密套件** 在请求前修改默认加密套件,确保客户端支持服务器所需的加密算法: ```python import requests.packages.urllib3.util.ssl_ requests.packages.urllib3.util.ssl_.DEFAULT_CIPHERS = 'ALL' ``` 3. **禁用证书验证(仅用于测试环境)** 如果是测试环境且证书问题不影响业务逻辑,可以临时禁用证书验证: ```python import ssl ssl._create_default_https_context = ssl._create_unverified_context ``` **注意**:此方法不应在生产环境中使用,因为它会降低安全性。 4. **使用 `pyOpenSSL` 等第三方库增强 SSL 支持** 安装 `pyOpenSSL`、`ndg-httpsclient` 和 `pyasn1` 可增强 SSL/TLS 支持,有助于解决握手失败问题: ```bash pip install pyOpenSSL ndg-httpsclient pyasn1 ``` 5. **手动指定 SSL 上下文进行连接** 对于更精细的控制,可以在建立连接时手动指定 SSL 上下文: ```python import ssl import socket hostname = "www.example.com" context = ssl.SSLContext(ssl.PROTOCOL_TLSv1_2) sock = context.wrap_socket(socket.socket(socket.AF_INET, socket.SOCK_STREAM), server_hostname=hostname) sock.connect((hostname, 443)) ``` 6. **检查服务器配置** 确保服务器配置支持现代 TLS 协议版本和通用加密套件,并且证书链完整、有效且受信任。使用工具如 `openssl s_client -connect example.com:443` 可以检查服务器端的 SSL/TLS 配置。 7. **设置最低 TLS 版本(适用于特定环境)** 在某些环境中,可以通过环境变量强制使用特定的 TLS 版本,例如: ```bash export GAM_TLS_MIN_VERSION=TLSv1.2 ``` ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值