解决 Node.js 中 "SSL routines:final_renegotiate:unsafe legacy renegotiation disabled" 错误

问题背景

当你使用 Node.js 与一些较旧的服务器(特别是 IIS)建立 HTTPS 连接时,可能会遇到以下错误:

SSL routines:final_renegotiate:unsafe legacy renegotiation disabled

这个错误源于一个已知的安全漏洞 CVE-2009-3555,Node.js 从版本 17/18 开始移除了对不安全旧版 SSL 重新协商的支持,以增强安全性。

问题根源

CVE-2009-3555 安全漏洞

该漏洞允许攻击者在 SSL/TLS 会话中注入任意明文,可能导致会话劫持和其他安全问题。因此,现代 Node.js 版本默认禁用了这种不安全的旧版重新协商方式。

IIS 服务器的兼容性问题

许多旧版 IIS 服务器仍然使用这种不安全的重新协商方式,而 Node.js 的默认配置不再允许这种连接。这就是为什么你会遇到这个错误,即使尝试使用 Node.js 标志也无法忽略它。

解决方案

使用自定义 HTTPS Agent 允许旧版连接

对于必须与这些旧服务器通信的情况,可以通过创建自定义 HTTPS Agent 来允许旧版 SSL 连接:

import crypto from 'crypto';
import https from 'https';
import axios from 'axios';

const allowLegacyRenegotiationforNodeJsOptions = {
  httpsAgent: new https.Agent({
    secureOptions: crypto.constants.SSL_OP_LEGACY_SERVER_CONNECT,
  }),
};

export const request = axios.create({
  ...allowLegacyRenegotiationforNodeJsOptions,
  headers: {
    Accept: 'application/json',
    'Content-Type': 'application/json',
  },
  // ... 
});

方案说明

  1. crypto.constants.SSL_OP_LEGACY_SERVER_CONNECT
    这个选项明确告诉 Node.js 允许与使用旧版 SSL 重新协商的服务器建立连接。

  2. 自定义 HTTPS Agent
    通过创建自定义的 https.Agent,我们可以覆盖默认的安全设置,同时保持其他安全功能不变。

安全注意事项

虽然这个解决方案可以解决问题,但需要注意:

  1. 安全风险
    启用旧版重新协商会降低连接的安全性,可能使你的应用面临中间人攻击等风险。

  2. 临时解决方案
    这应该被视为临时解决方案,长期来看应该升级服务器端以支持现代 SSL/TLS 协议。

  3. 范围限制
    尽量只对特定的、必要的连接启用此选项,而不是全局设置。

替代方案

如果可能,考虑以下更安全的替代方案:

  1. 升级服务器
    将 IIS 服务器升级到支持现代 TLS 协议的版本。

  2. 使用代理
    在中间层设置一个代理服务器,处理与旧服务器的安全连接,而你的 Node.js 应用则与代理使用现代协议通信。

  3. 联系服务提供商
    如果是第三方服务,联系他们升级其 SSL/TLS 配置。

总结

当遇到 "SSL routines:final_renegotiation:unsafe legacy renegotiation disabled" 错误时,可以通过创建自定义 HTTPS Agent 并设置 SSL_OP_LEGACY_SERVER_CONNECT 选项来解决与旧版服务器的兼容性问题。但请记住,这只是一个临时解决方案,从安全角度考虑,应该尽快升级服务器端以支持现代安全协议。

在实施此解决方案时,务必评估潜在的安全风险,并尽可能限制其使用范围,只在绝对必要的情况下启用旧版 SSL 重新协商支持。

posted @ 2025-08-05 19:36  guangzan  阅读(224)  评论(0)    收藏  举报