9

The best way to solve this would be to update the SSL endpoint I'm trying to connect to but I don't have the ability too.

I'm trying to reach a SOAP endpoint (it's painful) for an application that is barily being maintained and thus probably won't be able to get the proper SSL patch.

It's sitting behind a proxy that is doing active SSL rewrites and could also be to blame for the error:


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)
})    

Error:

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

From what I found here, it's possible to create a custom OpenSSL config file allowing unsafe legacy renegotiation. And using Node's --openssl-config flag, it should be possible to "ignore" the renegotiation. I've tried writing a custom config file as written in the first link and passing it in but with no avail.

This question has been asked before, though reverting to an older verision of Node would not be ideal.

What might be some other wasys to resolve this?

BobserLuck
  • 401
  • 1
  • 3
  • 13
  • 1
    A simple way to make it work per project. See this answer : https://stackoverflow.com/a/76161893/10179467 – Michaël May 03 '23 at 09:15

3 Answers3

18

As you already have found, this error is coming from CVE-2009-3555, this is IIS issue, so it even won't be ignored using node flags. Since node 17 or 18, they removed the OpenSSL option to accept legacy servers.

I think a better solution in your case is passing httpsAgent with the option. soap.js uses Axios as of v0.40.0 according to the readme, so you should set the request param like this:

const crypto = require('crypto')

const options = {
  request: axios.create({
      // axios options
      httpsAgent: new https.Agent({
        // for self signed you could also add
        // rejectUnauthorized: false,

        // allow legacy server
        secureOptions: crypto.constants.SSL_OP_LEGACY_SERVER_CONNECT,
      }),
    }),
  }

https.Agent's secureOptions is a numeric bitmask of the SSL_OP_* options.

Toan Nguyen
  • 11,263
  • 5
  • 43
  • 59
MadDocNC
  • 670
  • 5
  • 17
  • Thanks for the answer. Currently, I had something working with Node 16 LTS and strong-soap. If I can communicate properly with soap.js with the extra Axios config, I'd gladdly switch over to a version that won't be depricated in less than a year. Will give it a shot tomorrow and will accept the answer if all goes well. – BobserLuck Nov 30 '22 at 04:25
  • 1
    Thanks man! That worked perfectly! Spent so much time trying to figure this one out and now I don't have to wory about living in a depricated version of Node for a while. – BobserLuck Nov 30 '22 at 17:09
4

You can also setup the global configuration for OpenSSL when executing node process:

node --openssl-config=/openssl.cnf

--openssl-config: Load an OpenSSL configuration file on startup.

where openssl.cnf can be like:

nodejs_conf = openssl_init

[openssl_init]
ssl_conf = ssl_sect

[ssl_sect]
system_default = system_default_sect

[system_default_sect]
Options = UnsafeLegacyRenegotiation

Using nodejs_conf is required, since it will avoid conflict with other configuration files, see --openssl-shared-config for more info.

... it is recommended to use a configuration section specific to Node.js which is nodejs_conf and is default when this option is not used.

呂學洲
  • 1,123
  • 8
  • 19
0

To set this up globally,

For Windows: I added the following under my environment variables- NODE_OPTIONS: C:\path\to\openssl.cnf Then I did a restart and it works without changing my start command in package.json.

For Linux: Similarly environment variable will have to be set and terminal restart.

My openssl.cnf is the same as @呂學洲's answer. (https://stackoverflow.com/a/76033006/15559387)

I am not sure about the pitfalls of using this, but it is recommended to check for security measures before doing something like this on the production server.

Not sure why it works with Node version 16 and not with version 18.