5

I'm building a SSL crawler application where user pass in the domain name and NodeJS use tls library to retrieve the SSL certificate.

First, here is my codes:

server.js

const tls = require('tls');
var rootCas = require('ssl-root-cas/latest').create();
const fs = require('fs');

fs.readdirSync('./keys/intermediate_certs').forEach(file => {
    rootCas.addFile('./keys/intermediate_certs/' + file)
});

var secureContext = tls.createSecureContext({
    ca: rootCas
});

options = {
    host: host, //domain like google.com
    port: 443,
    secureContext: secureContext,
    ca: rootCas,
    rejectUnauthorized: true
};

var tlsSocket = tls.connect(options, function () {

   let rawCert = tlsSocket.getPeerCertificate()
   console.log(rawCert)
})

tlsSocket.on('error', (error) => {
   console.log(error)
   // [ERR_TLS_CERT_ALTNAME_INVALID] Hostname/IP does not match certificate's altnames: Host: zdns.cn. is not in the cert's altnames: DNS:*.fkw.com, DNS:fkw.com

   // unable to verify the first certificate or UNABLE_TO_VERIFY_LEAF_SIGNATURE
});

Problem is the nodejs application throwing error, according to the TLS documentation, the errors were from OpenSSL, however, when browsing the website and view certificate is showing all valid (even the common name matched exactly).

Here are some criteria:

  1. zdns.cn / www.zdns.cn is showing the error: ERR_TLS_CERT_ALTNAME_INVALID; When view cert from browser it show *.zdns.cn
  2. knet.cn / www.knet.cn is showing the error: unable to verify the first certificate; When view cert from browser it show www.knet.cn

Note: I included latest root CA from ssl-root-cas and also downloaded the intermediate certificate manually from CA site.

Jerry
  • 1,455
  • 1
  • 18
  • 39
  • 1
    Could you please provide the nodejs version you are using? An example of the file ```ssl-root-cas/latest``` would also be good to have – Mestre San May 15 '20 at 19:48
  • I'm not sure about the implementation in NodeJS, but I have run across other hostname verifiiers that didn't inspect alternate names well. Check out this answer: https://stackoverflow.com/questions/47849427/node-js-tls-connections-without-hostname-verification. You can override the `checkServerIdentity` to ignore it, or implement a more robust one that works for you. Honestly, if you are just crawling the certs, you may want to skip all of the hostname and other verifications on the cert, potentially manually looking at them and adding the results to your output. – rfestag May 16 '20 at 20:03

1 Answers1

0

You are getting that error specifically because of your rejectUnauthorized parameter. The certificate is presenting *.fkw.com as the CN, and it is presenting *.fkw.com and fkw.com as alternate names. None of those match zdns.cn or www.zdns.cn.

If you are just crawling to get the certs, you may want to drop the rejectUnauthorized. Alternatively, the error does seem to display the rest of the certificate information in the error. So you could keep it as is and include in your output information about why the certificate is untrusted/invalid. That seems like valuable information for a crawler pulling certs.

rfestag
  • 1,913
  • 10
  • 20