Ignore invalid self-signed ssl certificate in node.js with https.request?

node.jsHttpsSsl Certificate

node.js Problem Overview


I'm working on a little app that logs into my local wireless router (Linksys) but I'm running into a problem with the router's self-signed ssl certificate.

I ran wget 192.168.1.1 and get:

ERROR: cannot verify 192.168.1.1's certificate, issued by `/C=US/ST=California/L=Irvine/O=Cisco-Linksys, LLC/OU=Division/CN=Linksys/[email protected]':
Self-signed certificate encountered.
ERROR: certificate common name `Linksys' doesn't match requested host name `192.168.1.1'.
To connect to 192.168.1.1 insecurely, use `--no-check-certificate'.

In node, the error being caught is:

{ [Error: socket hang up] code: 'ECONNRESET' }

My current sample code is:

var req = https.request({ 
    host: '192.168.1.1', 
    port: 443,
    path: '/',
    method: 'GET'

}, function(res){

    var body = [];
    res.on('data', function(data){
        body.push(data);
    });

    res.on('end', function(){
        console.log( body.join('') );
    });

});
req.end();

req.on('error', function(err){
    console.log(err);
});

How can I go about getting node.js to do the equivalent of "--no-check-certificate"?

node.js Solutions


Solution 1 - node.js

Cheap and insecure answer:

Add

process.env["NODE_TLS_REJECT_UNAUTHORIZED"] = 0;

in code, before calling https.request()

A more secure way (the solution above makes the whole node process insecure) is answered in this question

Solution 2 - node.js

In your request options, try including the following:

   var req = https.request({ 
      host: '192.168.1.1', 
      port: 443,
      path: '/',
      method: 'GET',
      rejectUnauthorized: false,
      requestCert: true,
      agent: false
    },

Solution 3 - node.js

Don't believe all those who try to mislead you.

In your request, just add:

ca: [fs.readFileSync([certificate path], {encoding: 'utf-8'})]

If you turn on unauthorized certificates, you will not be protected at all (exposed to MITM for not validating identity), and working without SSL won't be a big difference. The solution is to specify the CA certificate that you expect as shown in the next snippet. Make sure that the common name of the certificate is identical to the address you called in the request(As specified in the host):

What you will get then is:

var req = https.request({ 
      host: '192.168.1.1', 
      port: 443,
      path: '/',
      ca: [fs.readFileSync([certificate path], {encoding: 'utf-8'})],
      method: 'GET',
      rejectUnauthorized: true,
      requestCert: true,
      agent: false
    },

Please read this article (disclosure: blog post written by this answer's author) here in order to understand:

  • How CA Certificates work
  • How to generate CA Certs for testing easily in order to simulate production environment

Solution 4 - node.js

Add the following environment variable:

NODE_TLS_REJECT_UNAUTHORIZED=0

e.g. with export:

export NODE_TLS_REJECT_UNAUTHORIZED=0

(with great thanks to Juanra)

Solution 5 - node.js

Adding to @Armand answer:

> Add the following environment variable: > > NODE_TLS_REJECT_UNAUTHORIZED=0 e.g. with export: > > export NODE_TLS_REJECT_UNAUTHORIZED=0 (with great thanks to Juanra)

If you on windows usage:

set NODE_TLS_REJECT_UNAUTHORIZED=0

Thanks to: @weagle08

Solution 6 - node.js

You can also create a request instance with default options:

require('request').defaults({ rejectUnauthorized: false })

Solution 7 - node.js

For meteorJS you can set with npmRequestOptions.

HTTP.post(url, {
    npmRequestOptions: {
        rejectUnauthorized: false // TODO remove when deploy
    },
    timeout: 30000, // 30s
    data: xml
}, function(error, result) {
    console.log('error: ' + error);
    console.log('resultXml: ' + result);
});

Solution 8 - node.js

Or you can try to add in local name resolution (hosts file found in the directory etc in most operating systems, details differ) something like this:

192.168.1.1 Linksys 

and next

var req = https.request({ 
    host: 'Linksys', 
    port: 443,
    path: '/',
    method: 'GET'
...

will work.

Solution 9 - node.js

So, my company just switched to Node.js v12.x. I was using NODE_TLS_REJECT_UNAUTHORIZED, and it stopped working. After some digging, I started using NODE_EXTRA_CA_CERTS=A_FILE_IN_OUR_PROJECT that has a PEM format of our self signed cert and all my scripts are working again.

So, if your project has self signed certs, perhaps this env var will help you.

Ref: https://nodejs.org/api/cli.html#cli_node_extra_ca_certs_file

Solution 10 - node.js

try export NODE_TLS_REJECT_UNAUTHORIZED=0

Solution 11 - node.js

When you cannot control the request creation

When using packages you sometimes don't have the option to set the correct settings on the request call, nor does the package offer you a way to inject a request.

However you might still want to avoid the insecure NODE_TLS_REJECT_UNAUTHORIZED=0 and opt for only having an insecure connection to a specified target.

This is how I solved the issue:

// check if host and port fit your application
function isSelf(host, port) {
  return host === myHost && port === myPort;
}

// get the built in tls module and overwrite the default connect behavior 
const tls = require("tls");
const _connect = tls.connect;
function wrappedConnect(options, secureConnectListener) {
  if (isSelf(options.host, options.port)) {
    options.rejectUnauthorized = false;
  }
  return _connect(options, secureConnectListener);
}
tls.connect = wrappedConnect;

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionGeuisView Question on Stackoverflow
Solution 1 - node.jsJuanraView Answer on Stackoverflow
Solution 2 - node.jsMeg SharkeyView Answer on Stackoverflow
Solution 3 - node.jsHesham YassinView Answer on Stackoverflow
Solution 4 - node.jsArmandView Answer on Stackoverflow
Solution 5 - node.jshackp0intView Answer on Stackoverflow
Solution 6 - node.jsEduardoView Answer on Stackoverflow
Solution 7 - node.jsdigz6666View Answer on Stackoverflow
Solution 8 - node.jspiafView Answer on Stackoverflow
Solution 9 - node.jswayneseymourView Answer on Stackoverflow
Solution 10 - node.jsMeeraj KanaparthiView Answer on Stackoverflow
Solution 11 - node.jsstrom-und-spieleView Answer on Stackoverflow