Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

EPROTO C0BAF076:error:0A000152 error reported in PM2 log from this version #45378

Closed
akc42 opened this issue Nov 8, 2022 · 25 comments
Closed
Labels
crypto Issues and PRs related to the crypto subsystem. https Issues or PRs related to the https subsystem.

Comments

@akc42
Copy link

akc42 commented Nov 8, 2022

Version

18.12.1

Platform

Linux pas 5.10.63-v7+ #1457 SMP Tue Sep 28 11:25:31 BST 2021 armv7l GNU/Linux

Subsystem

at WriteWrap.onWriteComplete [as oncomplete] (node:internal/stream_base_commons:94:16)

What steps will reproduce the bug?

This is a raspberry pi node.js api http server mainly proxied to from nginx http/2 server front ending Chrome browser clients.

There are a few internal processes running on the raspberry pi that are also nodejs based using the http connector directly.

the actual fault printed in the logs is

 Error: write EPROTO C0BAF076:error:0A000152:SSL routines:final_renegotiate:unsafe legacy renegotiation disabled:../deps/openssl/openssl/ssl/statem/extensions.c:922:
 
     at WriteWrap.onWriteComplete [as oncomplete] (node:internal/stream_base_commons:94:16) {
   errno: -71,
   code: 'EPROTO',
   syscall: 'write'
 }

the process that fails also makes calls to a sqlserver database using the tedious connection to another machine. So I don't know if this an incoming our outgoing connection fail

How often does it reproduce? Is there a required condition?

This is a production system which was upgraded to 18.12.1 last night (from 16.17.0) and has been running all day with the normal 5 or 6 users. The first time it failed was midday today, but then but since about 3:20 this afternoon until now about every 20 minutes.

What is the expected behavior?

no failures

What do you see instead?

The information given above in the logs.

Additional information

No response

@Trott
Copy link
Member

Trott commented Nov 8, 2022

That would seem to be a message coming from OpenSSL. Do you know if you're node binary has OpenSSL bundled or if it is using your system OpenSSL?

@akc42
Copy link
Author

akc42 commented Nov 9, 2022

@Trott I haven't specifically linked it, I use nvm and I just did an nvm install v18.12.1 on the raspberry pi to install node. I then set that version as the default. For now I have reverted to v16.17.0 (although I see that needs updating).

The raspberry pi is running Debian stable and hasn't been updated for a while. openssl is installed

@targos
Copy link
Member

targos commented Nov 9, 2022

It's possible that running Node.js with --openssl-legacy-provider fixes this.

@afbpinheiro
Copy link

I'm having the same problem, also after upgrading from node v16.15.1 to v18.12.1.
Sadly @targos solution doesn't work.

Here's a small snippet so anyone reproduce the problem:

https.get('https://scsanctions.un.org', (res) => {
    console.log(res);
}).on('error', (err) => {
    console.log(err);
});

@targos
Copy link
Member

targos commented Nov 10, 2022

@afbpinheiro thanks for the small reproduction. /cc @nodejs/crypto I confirm that it starts failing with Node.js 17 and --openssl-legacy-provider doesn't make it work.

@targos targos added crypto Issues and PRs related to the crypto subsystem. https Issues or PRs related to the https subsystem. labels Nov 10, 2022
@arhart
Copy link
Contributor

arhart commented Nov 11, 2022

Is this expected behavior? a scan reports for scsanctions.un.org "There is no support for secure renegotiation." and "This server supports TLS 1.1. Grade capped to B."

@arhart
Copy link
Contributor

arhart commented Nov 11, 2022

Possibly related workaround to disable the security check: https://stackoverflow.com/a/72245418

@afbpinheiro
Copy link

@arhart, genuinely asking: why should this be expected behavior?

@bnoordhuis
Copy link
Member

Because it's unsafe. It essentially allows a man-in-the-middle attacker to hijack HTTPS sessions. The option to enable it is called SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION for a reason.

@afbpinheiro
Copy link

@bnoordhuis I know it's unsafe and I know why it's unsafe, I just don't understand why throwing an error in those situations could be considered the default behavior. Therefore my question.

@bnoordhuis
Copy link
Member

What else would you have it do? Quietly do the unsafe thing anyway?

@afbpinheiro
Copy link

There are multiple possibilites:

  1. Keep the same behavior as pre-v17 versions, the "quietly do the unsafe thing anyway" option
  2. Emit a warning stating the possible consequences of the connection but do it anyway
  3. Throw an error explaining the possible consequences and have a flag so the user can decide to do it anyway

Each option has its own trade-offs and I don't have the knowledge to weight their advantages and disadvantages.
I just don't see how throwing an error and make the user find a workaround because node won't make the request can be considered default behavior.

In my use case, I use node to connect to third parties, from which I don't have authority to decide how to manage the security of their website. I can't do much more than request them to do it.
From node's side, I can just downgrade the version as a workaround, sure. But I think the current (possible default) behavior is just not ok.

@targos
Copy link
Member

targos commented Nov 14, 2022

You can opt into the insecure behavior by passing secureOptions: crypto.constants.SSL_OP_LEGACY_SERVER_CONNECT in the options for your connection.

@arhart
Copy link
Contributor

arhart commented Nov 14, 2022

@afbpinheiro 1 and 2 would be security vulnerabilities. Even if a warning is seen, it won't be in time to have prevented the unsafe thing.

If you are proposing a command line argument or an option, those might be features that could be added. Are they enough better than configuring OpenSSL through the configuration section to justify extra complexity?

Maybe this could be documented more clearly, but where? It's an error coming from OpenSSL, and OpenSSL documents this behavior and it's configuration option.

@arhart
Copy link
Contributor

arhart commented Nov 14, 2022

Thanks, @targos I didn't realize that was plumbed!

@arhart
Copy link
Contributor

arhart commented Nov 14, 2022

I think this is the desired option: SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION

@targos
Copy link
Member

targos commented Nov 14, 2022

SSL_OP_LEGACY_SERVER_CONNECT is the option that went from enabled by default in OpenSSL 1.1.1 to disabled by default in OpenSSL 3.0.

See https://www.openssl.org/docs/man3.0/man7/migration_guide.html:

Secure renegotiation is now required by default for TLS connections

Support for RFC 5746 secure renegotiation is now required by default for SSL or TLS connections to succeed. Applications that require the ability to connect to legacy peers will need to explicitly set SSL_OP_LEGACY_SERVER_CONNECT. Accordingly, SSL_OP_LEGACY_SERVER_CONNECT is no longer set as part of SSL_OP_ALL.

@pumano
Copy link

pumano commented Nov 21, 2022

few folks from our company got that errors from 18.12.1 LTS too (macos m1) also from linux (1 person).

@akc42
Copy link
Author

akc42 commented Nov 22, 2022

I have discovered that it is just one service provider that we use that fails in this manner (and their sandbox url does not fail so it was not picked up in development). I have added the cryto option suggested by @bnoordhuis (secureOptions: crypto.constants.SSL_OP_LEGACY_SERVER_CONNECT) to the options object that I pass to the https.request call and it works fine, so I am closing this issue

@akc42 akc42 closed this as completed Nov 22, 2022
@veemata
Copy link

veemata commented Jan 17, 2023

hi akc42
where should i add this secureOptions: crypto.constants.SSL_OP_LEGACY_SERVER_CONNECT option. I am unable to download anything with npm

@akc42
Copy link
Author

akc42 commented Jan 18, 2023

@veemata like this

import https from 'node:https';
import crypto from 'node:crypto';
...
        const options = {
          method: 'POST',
          headers: {
            'Content-Type': 'application/x-www-form-urlencoded',
            'Content-Length': Buffer.byteLength(postData)
          },
          rejectUnauthorized: false,
          secureOptions: crypto.constants.SSL_OP_LEGACY_SERVER_CONNECT
        };
        const reply = await new Promise((accept, reject) => {
        
            const request = https.request(process.env.PAS_SMS_BASE,options, res => bodyParser(res,accept,reject)).on('error', (err) => {
              //this tends to happen if certificate error
              debug('Cert Error Happened with err', err);
              reject(new Error('Bad Certificate at SMS Senders Web Site'));
            })
            request.write(postData)
            request.end();

        }); 

@TheBrenny
Copy link

@veemata I'm hitting the same problem (the bug is inside NPM itself, not Node (I think?)). See this issue: npm/cli#6070

@bondjag
Copy link

bondjag commented Apr 4, 2023

Hi Error: write EPROTO 9C5E0000:error:0A000152:SSL routines:final_renegotiate:unsafe legacy renegotiation disabled:c:\ws\deps\openssl\openssl\ssl\statem\extensions.c:922:, Facing this one while running the command
yarn add puppeteer

@lucas-labs
Copy link

I'm unable to download anything from npmjs registry (that is running npm i whatever) while being behind a corporate firewall. Downgrading to v16 is for now, the only option we have, since there's apparently no way to make npm set SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION

If someone finds a workaround, that would be very much appreciated

@DattaramNaik
Copy link

I am getting same error after updating node 12 to 18 kindly provide a solution for same.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
crypto Issues and PRs related to the crypto subsystem. https Issues or PRs related to the https subsystem.
Projects
None yet
Development

No branches or pull requests