如何修改Python requests使用的SSL密码套件?解决DH_KEY_TOO_SMALL错误
解决requests在OpenSSL 3.0环境下的DH_KEY_TOO_SMALL错误
问题原因
OpenSSL 3.0(Ubuntu 22.04、Windows 11默认版本)收紧了安全策略,默认要求DH密钥长度至少2048位,当服务器提供更小的DH密钥时会直接抛出DH_KEY_TOO_SMALL错误。而旧版本OpenSSL(1.1.1,Ubuntu 18.04、Windows 10默认)仅将此作为警告处理。Firefox能正常访问是因为它要么优先协商了ECDHE套件,要么对DH密钥限制更宽松。
你之前修改requests.packages.urllib3.util.ssl_.DEFAULT_CIPHERS无效,是因为新版本requests/urllib3不再直接依赖这个全局变量,或者全局修改无法覆盖特定请求的SSL配置。
解决方案
通过自定义HTTP适配器,针对目标域名配置SSL上下文,强制使用你指定的ECDHE密码套件并排除DH套件,避免触发DH密钥错误。
代码实现
import requests from requests.adapters import HTTPAdapter from urllib3.poolmanager import PoolManager import ssl class ECDHESSLAdapter(HTTPAdapter): def init_poolmanager(self, *args, **kwargs): # 创建默认SSL上下文,自动禁用不安全协议(SSLv3、TLSv1、TLSv1.1) ctx = ssl.create_default_context() # 指定要使用的ECDHE密码套件,并排除所有DH套件,强制使用ECDHE密钥交换 ctx.set_ciphers('ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:!DH') kwargs['ssl_context'] = ctx return super().init_poolmanager(*args, **kwargs) # 创建会话并挂载适配器,仅对目标域名生效 session = requests.Session() session.mount('https://api-mte.itespp.org', ECDHESSLAdapter()) # 发起请求 try: response = session.get("https://api-mte.itespp.org/markets/VirtualService/v2/?WSDL") response.raise_for_status() print("请求成功,状态码:", response.status_code) # 处理响应内容 except requests.exceptions.RequestException as e: print("请求失败:", str(e))
关键配置说明
ctx.set_ciphers(...):明确指定你需要的两个ECDHE套件,通过:!DH排除所有基于DH的密钥交换算法,确保握手时仅协商ECDHE套件,彻底规避DH密钥过小的问题。- 自定义适配器仅挂载到目标域名
api-mte.itespp.org,不会影响程序中其他请求的SSL配置,保证安全性。 ssl.create_default_context()默认禁用了SSLv3、TLSv1、TLSv1.1等不安全协议,仅保留TLSv1.2+,符合当前安全标准。
验证服务器兼容性
如果不确定服务器是否支持指定的ECDHE套件,可以用OpenSSL命令验证:
openssl s_client -connect api-mte.itespp.org:443 -cipher ECDHE-RSA-AES128-GCM-SHA256
如果输出中包含SSL handshake has read XXX bytes and written XXX bytes且没有错误,说明服务器支持该套件。
内容的提问来源于stack exchange,提问作者geckels1
相关产品推荐
相关产品推荐

