使用Python requests爬取内部页面遇DH_KEY_TOO_SMALL错误求新方案
解决
urllib3.exceptions.SSLError: [SSL: DH_KEY_TOO_SMALL] 错误 这个错误是因为你访问的内部站点使用了长度不足的DH密钥(通常小于2048位),而新版本Python依赖的OpenSSL默认启用了严格的安全策略,拒绝这种弱密钥的连接。下面是几个适配新版本环境的解决方法:
方法一:临时放宽OpenSSL安全策略(简单直接)
通过设置环境变量调整OpenSSL的安全级别,允许接受较短的DH密钥:
import os import requests # 临时设置OPENSSL_CONF为空,绕过默认严格策略(Linux/macOS适用) os.environ['OPENSSL_CONF'] = '/dev/null' # 或者更精准的方式,先创建一个临时配置文件(比如命名为temp_openssl.cnf),内容如下: # openssl_conf = default_conf # [default_conf] # ssl_conf = ssl_sect # [ssl_sect] # system_default = system_default_sect # [system_default_sect] # MinProtocol = TLSv1.2 # CipherString = DEFAULT:@SECLEVEL=1 # 然后设置环境变量指向这个文件 # os.environ['OPENSSL_CONF'] = '/path/to/temp_openssl.cnf' # 正常发起请求,带上你的站点证书 response = requests.get('https://你的内部站点地址', verify='/path/to/你的证书.pem') print(response.status_code)
SECLEVEL=1会放宽密钥长度限制,但仍保留基本的SSL安全,比直接关闭验证安全得多。
方法二:自定义requests的SSL适配器(更安全,仅针对当前请求生效)
创建一个自定义的HTTP适配器,修改SSL上下文的安全级别,只影响当前请求会话:
import requests from requests.adapters import HTTPAdapter from urllib3.poolmanager import PoolManager from urllib3.util.ssl_ import create_urllib3_context class DHKeyAdapter(HTTPAdapter): def init_poolmanager(self, *args, **kwargs): # 创建自定义SSL上下文,调整安全级别 context = create_urllib3_context(ciphers='DEFAULT:@SECLEVEL=1') kwargs['ssl_context'] = context return super().init_poolmanager(*args, **kwargs) # 初始化session并挂载适配器 session = requests.Session() session.mount('https://', DHKeyAdapter()) # 发起请求,带上证书 response = session.get('https://你的内部站点地址', verify='/path/to/你的证书.pem') print(response.status_code)
这种方法不会全局修改OpenSSL配置,只对这个session生效,安全性更高。
重要提醒
- 绝对不要随便用
verify=False,这会完全跳过SSL证书验证,可能导致中间人攻击,尤其是内部站点通常涉及敏感数据。 - 如果是Windows环境,
/dev/null的方式不适用,优先用第二种自定义适配器的方法。 - 确认你的站点证书配置正确,虽然当前错误是DH密钥问题,但证书错误也可能引发SSL相关异常。
内容的提问来源于stack exchange,提问作者Mark Phillips
相关产品推荐
相关产品推荐

