I used the following code to get the server TLS certificate for stackoverflow.com:
const tls = require('tls');
const conn = tls.connect({
host: 'stackoverflow.com',
port: 443,
rejectUnauthorized: false
}, () => {
const cert = conn.getPeerCertificate(false);
console.log(cert);
conn.destroy();
});
The result includes the following:
- subject:
{ CN: '*.stackexchange.com' } - issuer:
{ C: 'US', O: "Let's Encrypt", CN: 'R3' } - valid_from:
Dec 3 14:00:52 2020 GMT - valid_to:
Mar 3 14:00:52 2021 GMT - fingerprint256:
C6:D3:6E:68:38:EC...
Note that it is an expired certificate.
By contrast, when I visit stackoverflow.com in Firefox, it loads a certificate with the following details:
- Not before:
Sun, 06 Mar 2022 14:17:27 GMT - Not after:
Sat, 04 Jun 2022 14:17:26 GMT - SHA-256:
04:F7:14:2A:28:EF:1F...
It appears Node is obtaining an old certificate. Perhaps it is cached somewhere?
My platform is:
- Node v17.8.0
- Linux, x64, Manjaro
>Solution :
I get the same invalid certificate with your original code, so I took a look at the documentation, and it has the following interesting tidbit:
Unlike the
httpsAPI,tls.connect()does not enable the SNI
(Server Name Indication) extension by default, which may cause some
servers to return an incorrect certificate or reject the connection
altogether. To enable SNI, set theservernameoption in addition to
host.
Adding the servername option:
const tls = require('tls');
const conn = tls.connect({
host: 'stackoverflow.com',
servername: 'stackoverflow.com',
port: 443,
rejectUnauthorized: false
}, () => {
const cert = conn.getPeerCertificate(false);
console.log(cert);
conn.destroy();
});
I obtain a valid certificate:
subject: [Object: null prototype] { CN: '*.stackexchange.com' },
[...]
valid_from: 'Mar 6 14:17:27 2022 GMT',
valid_to: 'Jun 4 14:17:26 2022 GMT',
[...]