[Error: unable to get issuer certificate] code: 'UNABLE_TO_GET_ISSUER_CERT'

using node.js

var hardhttps=require('hardhttps');
hardhttps.globalAgent.options.ca=require('ssl-root-cas/latest').inject().addFile('/etc/letsencrypt/lets-encrypt-x3-cross-signed.pem');

var pem={
    key:require('fs').readFileSync('/etc/letsencrypt/live/mysite.com/privkey.pem','utf8')
,   cert:require('fs').readFileSync('/etc/letsencrypt/live/mysite.com/fullchain.pem','utf8')
,   ca:require('fs').readFileSync('/etc/letsencrypt/lets-encrypt-x3-cross-signed.pem','utf8')
,   pass:'xxxx'
    }

var server=(hardhttps.createServer({key:pem.key,cert:pem.cert,ca:[pem.ca],passphrase:pem.pass})).listen(server);

It just errors with [Error: unable to get issuer certificate] code: 'UNABLE_TO_GET_ISSUER_CERT' when ever I try to connect via my additional server

Hi @benzmuircroft, if you’re explicitly using lets-encrypt-x3-cross-signed.pem, maybe you should be using chain.pem instead of fullchain.pem? (fullchain.pem contains a copy of that and maybe that’s a sign that it’s redundant and confusing to your server software.)

You should be able to see exactly what certs are being sent back by trying to connect using

openssl s_client -connect localhost:443

(or wherever the server is listening instead of localhost:443). The received certificate data will be displayed at the top of the output, so you can see what’s missing. (Or you can use ssllabs.com to diagnose it if you don’t mind having outsiders looking at your server.)

Hey schoen,

If I use chain.pem instead of fullchain.pem I get the error

node /var/sentora/hostdata/zadmin/private_js/N.dg.js
_tls_common.js:85
c.context.setKey(options.key, options.passphrase);
^

Error: error:0B080074:x509 certificate routines:X509_check_private_key:key values mismatch
at Error (native)
at Object.createSecureContext (_tls_common.js:85:19)
at Server (_tls_wrap.js:736:25)
at new Server (https.js:17:14)
at Object.exports.createServer (https.js:37:10)
at Object.createServer (/var/sentora/hostdata/zadmin/node_modules/hardhttps/hardhttps.js:63:22)
at Object.G.listen (/var/sentora/hostdata/zadmin/private_js/N.dg.js:41:27)
at Object. (/var/sentora/hostdata/zadmin/private_js/N.dg.js:147:19)
at Module._compile (module.js:435:26)
at Object.Module._extensions…js (module.js:442:10)

If I use the command openssl s_client -connect localhost:8000

I get:

CONNECTED(00000003)
depth=2 O = Digital Signature Trust Co., CN = DST Root CA X3
verify return:1
depth=1 C = US, O = Let’s Encrypt, CN = Let’s Encrypt Authority X3
verify return:1
depth=0 CN = mysite.com
verify return:1

Certificate chain
0 s:/CN=mysite.com
i:/C=US/O=Let’s Encrypt/CN=Let’s Encrypt Authority X3
1 s:/C=US/O=Let’s Encrypt/CN=Let’s Encrypt Authority X3
i:/O=Digital Signature Trust Co./CN=DST Root CA X3

Server certificate
-----BEGIN CERTIFICATE-----
MIIFFDCCA/ygAwIBAgISA2P3iyamRm1uxn1fQ57sITaWMA0GCSqGSIb3DQEBCwUA
MEoxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MSMwIQYDVQQD
ExpMZXQncyBFbmNyeXB0IEF1dGhvcml0eSBYMzAeFw0xNjA0MjgyMDA4MDBaFw0x
NjA3b2RzcHJvdmlkZXIuxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Y29tMIH+BgNVHSAEgfYwgfMwCAYGZ4EMAQIBMIHmBgsrBgEEAYLfEwEBATCB1jAm
BggrBxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxcmcwgasGCCsGAQUF
BwICMIGeDIGbVGhpcyBDZXJ0aWZpY2F0ZSBtYXkgb25seSBiZSByZWxpZWQgdXBv
biBieSBxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxNjb3JkYW5jZSB3aXRo
IHRoZSBDZXJ0aWZpY2F0ZSBQb2xpY3kgZm91bmQgYXQgaHR0cHM6Ly9sZXRzZW5j
cnlwdC5vcmcvcmVwb3NpdG9yeS8wDQYJKoZIhvcNAQELBQADggEBABrxBneTgrjO
JTfrItb9kTixuuSsutbdQrO+ad7LmvARRKGqvJyGP1QuP9xGZgvkOUx4b2Ne91kQ
9mBTstg+WgxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxHkb69n/2NzoLy
dghFvtaQYFWjWQZBL9mbHA1ga2cS/Ri2Vo0mHyYr9bEoZcQBLVsvdQcS1I9olG9b
EGZtrhG/Zc95nSb2MjL4T0skEqQtZvrj/KGA82OO8fjMHDuWKG5eOdNlofBfjpWY
mjspGjnfcPoX7Oa3X6CvkrAsfRAPl1CirZjc09WsjbVFK87GuL6CH1VlNwgSLd+I
ERfmKblDYMM=
-----END CERTIFICATE-----
subject=/CN=mysite.com
issuer=/C=US/O=Let’s Encrypt/CN=Let’s Encrypt Authority X3

No client certificate CA names sent
Server Temp Key: ECDH, prime256v1, 256 bits

SSL handshake has read 3191 bytes and written 397 bytes

New, TLSv1/SSLv3, Cipher is ECDHE-RSA-AES256-SHA
Server public key is 2048 bit
Secure Renegotiation IS supported
Compression: NONE
Expansion: NONE
SSL-Session:
Protocol : TLSv1.2
Cipher : ECDHE-RSA-AES256-SHA
Session-ID: B856F5xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxCA3C45A11A
Session-ID-ctx:
Master-Key: 1C7EA41388Exxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0543490A6A99A6BE1A03C06
Key-Arg : None
Krb5 Principal: None
PSK identity: None
PSK identity hint: None
TLS session ticket lifetime hint: 300 (seconds)
TLS session ticket:
0000 - be cd e2 7e f6 1e 37 c7-3a f5 4d 23 db 90 da c3 …~…7.:.M#…
0010 - 77 9f 98 e2 95 db f0 b3-ff aa 94 61 49 18 09 56 w…aI…V
0020 - f8 97 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 71 …“Z!.9[!g.>.MUq
0030 - a8 49 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 98 0a .I-…AU…9…
0040 - 31 ee xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 41 58 1./TXg%.+p…AX
0050 - 88 43 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 29 .C…T.vl1…|%)
0060 - 99 ed xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 7f 5e …$5.y.N…W.s…^
0070 - e5 be xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 5a …”.?Z
0080 - 43 e3 6e 25 bb 97 1c 77-92 85 46 c3 f7 d1 d2 fd C.n%…w…F…
0090 - 9f 65 25 52 5a 94 c6 bb-ce 7d 7c 36 2a e6 7d b7 .e%RZ…}|6*.}.
00a0 - ee 90 98 af 83 57 56 fb-df 63 b4 02 25 da 46 af …WV…c…%.F.
00b0 - 46 33 00 bb 21 81 d1 2a-68 d6 ba 85 b3 88 32 bd F3…!..*h…2.

Start Time: 1462408767
Timeout   : 300 (sec)
Verify return code: 0 (ok)

I’ve xxxxxxx some things in there btw

ssllabs.com says

I have a problem with POODLE (SSLv3)

and

a few places Incorrect certificate because this client doesn’t support SNI

I’ve linked it to this as no doubt other people may need a solution http://stackoverflow.com/questions/37039890/wss-letsencrypt-unable-to-get-issuer-cert

POODLE is a web server configuration issue, not a certificate or Let's Encrypt issue. Basically, SSLv3 is an insecure and depreciated protocol and shouldn't be offered by your server.

Don't worry too much about clients that don't support SNI. They tend to be quite old and I haven't seen one in actual use in many years. Those notifications are about reference browsers/platforms, and you only need to be concerned if you're still using one.

Thanks @DarkSteve! My main goal here is to achieve no error on UNABLE_TO_GET_ISSUER_CERT! I want to identify what this error means and fix it! After that I will kill POODLE! I am providing as much info as I have as asked by @schoen.

My work as a node.js developer is literally dead/on hold unless I get these two servers to talk.

Do you have any knowledge on UNABLE_TO_GET_ISSUER_CERT (vague error)?

No, sorry, I’ve read through everything you’ve posted and I’m not familiar with node.js or much of what you’re doing. Hopefully Schoen can answer you!

I just try to help out where I can. Sometimes telling you what isn’t the problem can stop you spending time on things that won’t help :wink:

What TLS client are you using to connect with that yields the UNABLE_TO_GET_ISSUER_CERT? Do you have a different client, such as a web browser, that you could use for comparison?

What TLS client are you using to connect

Both servers are centos 7 running node.js v4.0.0 the (built in tls for node is here TLS (SSL) | Node.js v4.9.1 Manual & Documentation)

As for the comparison: I can connect a browser to each server no problem using letsencrypt https but not server to server

Mind showing the client code? (Where you’re connecting to the server, not starting it.)

@pfg the client side code is:

var ws=new WebSocket('wss://'+host+':'+port);
ws.on('open',function(event){});

It does not need to verify the ca where as the server to server connection refuses without the ca

openssl verify -check_ss_sig /etc/letsencrypt/lets-encrypt-x3-cross-signed.pem
/etc/letsencrypt/lets-encrypt-x3-cross-signed.pem: OK

what if I change to directory where I’m keeping the lets-encrypt-x3-cross-signed.pem like inside public_html?

I’m not sure I follow. What’s the “server to server connection” here?

The code in your original post shows how you launch the HTTPS server.

If some other server connects to that server as well, that’s just another TLS client. “Server to server” is not a TLS concept. I’m interested in the code where you establish a connection from one server to the other.

Server 1 listens

var hardhttps=require('hardhttps');
hardhttps.globalAgent.options.ca=require('ssl-root-cas/latest').inject().addFile('/etc/letsencrypt/lets-encrypt-x3-cross-signed.pem');
var pem={
    key:require('fs').readFileSync('/etc/letsencrypt/live/mysite1.com/privkey.pem','utf8')
,   cert:require('fs').readFileSync('/etc/letsencrypt/live/mysite1.com/fullchain.pem','utf8')
,   ca:require('fs').readFileSync('/etc/letsencrypt/lets-encrypt-x3-cross-signed.pem','utf8')
,   pass:'xxxx'
    }
var server=(hardhttps.createServer({key:pem.key,cert:pem.cert,ca:[pem.ca],passphrase:pem.pass,requestCert:true})).listen(8004);
var wss=new ws.Server({server:server});
wss.on('connection',function(soc){
    soc.on('message',function(data){
        console.log(data);
        });});

Server 2 tries to connect

var hardhttps=require('hardhttps');
hardhttps.globalAgent.options.ca=require('ssl-root-cas/latest').inject().addFile('/etc/letsencrypt/lets-encrypt-x3-cross-signed.pem');
pem:{
    key:require('fs').readFileSync('/etc/letsencrypt/live/mysite2.com/privkey.pem','utf8')
,   cert:require('fs').readFileSync('/etc/letsencrypt/live/mysite2.com/fullchain.pem','utf8')//was chain.pen
,   ca:require('fs').readFileSync('/etc/letsencrypt/lets-encrypt-x3-cross-signed.pem','utf8')
,   pass:'xxxxxxxxxxx'
    }
var ws=new require('ws')('wss://mysite1:8004',{key:pem.key,cert:pem.cert,ca:[pem.ca],passphrase:pem.pass,requestCert:true});
var deinit=function(){
    try{ws.close();}catch(e){}
    return;
    };
var fail=function(e){
    console.log(e);
    deinit();
    };
ws.on('error',function(e){fail(e);});
ws.on('open',function(){
    ws.on("message",function(m){
        console.log(m);
        deinit();
        });
    try{
        ws.send('hello ...?');
        }
    catch(e){
        fail('tried to send a message');
        }});

server 2 the one that tries to connect gets the error not the listening server

There's no need to set any of that. Server 2 is just a TLS client requesting Server 1, it does not need the server's key or certificate file. You probably just want:

var ws=new require('ws')('wss://mysite1:8004');

Not sure if that's the fix - give it a try.

1 Like

Working!

Awesome Thanks @pfg