Docker中Python requests报DH_KEY_TOO_SMALL错误的原因及解决方法
问题原因与解决办法
我之前处理过类似的容器SSL兼容问题,刚好能帮到你,先拆解核心原因,再给两种可行的解决思路:
为什么会出现DH_KEY_TOO_SMALL?
你的python:3.6-slim镜像基于Debian发行版,自带的OpenSSL版本是1.1.0及以上——这个版本开始默认启用了SECLEVEL=2的严格安全策略,它会拒绝密钥长度小于2048位的DH密钥交换。而你本地Windows 10虚拟环境或Azure VM里的Python依赖的OpenSSL,要么版本较低,要么安全等级配置更宽松,所以能正常和使用弱DH密钥的网站建立连接。这就是容器里报错、本地正常的核心差异点。
解决方法
方法1:修改容器全局OpenSSL配置(简单直接)
在你的Dockerfile里添加一行命令,把OpenSSL的安全等级从2降到1,就能兼容弱DH密钥了:
FROM python:3.6-slim # 调整OpenSSL安全等级,允许弱DH密钥 RUN sed -i 's/DEFAULT@SECLEVEL=2/DEFAULT@SECLEVEL=1/g' /etc/ssl/openssl.cnf # 后续的依赖安装、脚本复制步骤 RUN pip install requests COPY your_script.py /app/ WORKDIR /app CMD ["python", "your_script.py"]
这个修改是全局的,容器里所有使用OpenSSL的应用都会采用较低的安全等级,适合你只跑这个脚本的场景。
方法2:在Python脚本里自定义SSL上下文(更灵活)
如果不想改动容器全局的SSL策略,可以给requests单独配置一个宽松的SSL上下文,只针对目标网站生效:
import requests import ssl from requests.adapters import HTTPAdapter from urllib3.poolmanager import PoolManager class WeakDHCompatibleAdapter(HTTPAdapter): def init_poolmanager(self, *args, **kwargs): # 创建默认SSL上下文,然后降低安全等级 ssl_context = ssl.create_default_context() ssl_context.set_ciphers('DEFAULT:@SECLEVEL=1') kwargs['ssl_context'] = ssl_context return super().init_poolmanager(*args, **kwargs) # 初始化session并挂载自定义适配器 session = requests.Session() # 把适配器挂载到目标网站的域名下,只影响该网站的请求 session.mount('https://你的目标网站域名', WeakDHCompatibleAdapter()) # 发送请求 response = session.get('https://目标网站的接口URL') print(response.status_code)
这种方法更稳妥,不会影响容器里其他可能运行的应用的SSL安全标准。
内容的提问来源于stack exchange,提问作者eacooqy
相关产品推荐
相关产品推荐

