Node.js下启用不安全旧版SSL协商的解决方案咨询
问题描述
需要连接一个维护不足的SOAP端点,无法为其打SSL补丁,也无权限更新该SSL端点。该端点位于执行主动SSL重写的代理之后,使用代码连接时出现两类错误:一是req.then is not a function,二是unsafe legacy renegotiation disabled。尝试过自定义OpenSSL配置文件并通过--openssl-config参数启动Node.js,但未生效;降级Node.js版本并非理想方案,求其他解决办法。
代码示例
var request = require("request") var soap = require("soap") const fs = require('fs') var specialRequest = request.defaults({ ca: fs.readFileSync("rewrite-example.pem") }) var options = { request: specialRequest } const WSDL = "https://SSL-rewrite.example?wsdl" soap.createClient(WSDL, options, function(err, client) { if(err) throw Error(err) })
错误信息
Uncaught TypeError: req.then is not a function at HttpClient.request (../node_modules/soap/lib/http.js:191:13) at Object.open_wsdl (../node_modules/soap/lib/wsdl/index.js:1271:20) at openWsdl (../node_modules/soap/lib/soap.js:70:16) at ../node_modules/soap/lib/soap.js:48:13 at _requestWSDL (../node_modules/soap/lib/soap.js:76:9) at Object.createClient (../node_modules/soap/lib/soap.js:94:5) > Uncaught: Error: write EPROTO C017726B8C7F0000:error:0A000152:SSL routines:final_renegotiate:unsafe legacy renegotiation disabled:../deps/openssl/openssl/ssl/statem/extensions.c:908
可行解决方案
1. 替换为支持Promise的HTTP客户端
第一个错误是因为当前soap版本要求传入的HTTP客户端返回Promise,但旧版request是回调式架构,不支持Promise。可以替换成axios或got这类支持Promise的库,同时配置SSL选项解决协商问题:
const axios = require('axios'); const https = require('https'); const soap = require('soap'); const fs = require('fs'); // 配置axios实例,加载代理CA证书并启用旧版SSL协商 const axiosInstance = axios.create({ httpsAgent: new https.Agent({ ca: fs.readFileSync("rewrite-example.pem"), secureOptions: require('constants').SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION }) }); // 封装axios适配soap的请求格式 const customRequest = (url, options, callback) => { axiosInstance({ url, method: options.method, data: options.body, headers: options.headers }) .then(response => { callback(null, { statusCode: response.status, body: response.data, headers: response.headers }); }) .catch(err => callback(err)); }; const options = { request: customRequest }; const WSDL = "https://SSL-rewrite.example?wsdl"; soap.createClient(WSDL, options, function(err, client) { if(err) throw Error(err); // 后续业务操作 });
2. 升级request库并配置SSL选项
若坚持使用request生态,可升级到支持Promise的request-promise-native,同时在代理选项中开启旧版SSL协商:
const request = require('request-promise-native'); const soap = require('soap'); const fs = require('fs'); const specialRequest = request.defaults({ ca: fs.readFileSync("rewrite-example.pem"), agentOptions: { secureOptions: require('constants').SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION } }); const options = { request: specialRequest }; const WSDL = "https://SSL-rewrite.example?wsdl"; soap.createClient(WSDL, options, function(err, client) { if(err) throw Error(err); });
3. 通过环境变量启用OpenSSL兼容模式
无需修改代码,设置环境变量让Node.js使用旧版OpenSSL兼容模式:
- Linux/macOS:
export NODE_OPTIONS="--openssl-legacy-provider"
- Windows:
set NODE_OPTIONS="--openssl-legacy-provider"
设置完成后运行Node.js脚本即可。
4. 验证代理CA证书正确性
确认rewrite-example.pem是SSL重写代理的根证书,而非原SOAP端点的证书。若证书不匹配,也会触发SSL连接错误,需替换为代理的CA证书。
内容的提问来源于stack exchange,提问作者BobserLuck
相关产品推荐
相关产品推荐

