GitLab CI/CD test阶段调用外部资源报错dh key too small
报错tls_process_ske_dhe:dh key too small的核心原因是你使用的node:16.15.1镜像基于Debian 11构建,系统内置OpenSSL 3.x默认安全等级为2,强制要求TLS握手时使用的Diffie-Hellman密钥长度不低于2048位,而你调用的外部HTTPS站点使用的DH密钥长度不足1024位,被OpenSSL直接拦截。
你本地环境能正常运行,是因为本地PC的OpenSSL默认安全等级更低(通常为1,允许1024位DH密钥)。之前在axios中配置的rejectUnauthorized: false仅跳过证书合法性校验,minVersion: "TLSv1"仅指定最低TLS版本,两个参数都不涉及DH密钥长度的校验规则,因此无法解决该问题。
按推荐优先级从高到低排列:
方案1:CI配置中临时调整OpenSSL安全等级(无需修改业务代码)
直接修改.gitlab-ci.yml,在测试执行前将容器内OpenSSL默认安全等级调整为1,兼容弱DH密钥站点,配置如下:image: node:16.15.1 stages: - test test-job: stage: test variables: NODE_OPTIONS: "--tls-min-v1.0" script: # 将OpenSSL默认安全等级从2降至1,允许1024位长度DH密钥 - sed -i 's/DEFAULT@SECLEVEL=2/DEFAULT@SECLEVEL=1/g' /etc/ssl/openssl.cnf - npm run test该方案仅修改当前CI任务容器内的配置,不会影响业务代码,也不需要更换基础镜像。
方案2:业务代码中显式指定Agent安全等级
如果不方便修改CI系统配置,可以在初始化axios的HTTPS Agent时,显式指定cipher列表的安全等级为1,修改后代码如下:const crypto = require('crypto'); const https = require('https'); const axios = require('axios'); const axiosOptions = { httpsAgent: new https.Agent({ rejectUnauthorized: false, minVersion: "TLSv1", // 为当前请求Agent单独设置安全等级为1 ciphers: 'ALL:!aNULL:!eNULL:@SECLEVEL=1', secureOptions: crypto.constants.SSL_OP_LEGACY_SERVER_CONNECT }) }; const axiosInstance = axios.create(axiosOptions); const response = await axiosInstance.get('https://www.some-domain.com/some-article.html');方案3:更换低版本Node基础镜像(临时应急用)
16.13.0及更早版本的Node官方镜像基于Debian 10构建,内置OpenSSL 1.1.1默认安全等级为1,不会强制校验DH密钥长度,直接修改CI配置中的镜像即可:image: node:16.13.0该方案不推荐长期使用,低版本Node存在未修复的安全漏洞。
注意:以上均为临时兼容方案,最优解决方式是联系所调用外部HTTPS站点的维护方,升级服务端TLS配置,使用2048位及以上长度的DH密钥,符合现代TLS安全规范。
内容的提问来源于stack exchange,提问作者fasenderos

