15

System: Windows 7

NodeJS version: 0.10.2

WS module: ws, last version

Error:

events.js:72
        throw er; // Unhandled 'error' event
              ^
Error: UNABLE_TO_VERIFY_LEAF_SIGNATURE
    at SecurePair. (tls.js:1283:32)
    at SecurePair.EventEmitter.emit (events.js:92:17)
    at SecurePair.maybeInitFinished (tls.js:896:10)
    at CleartextStream.read [as _read] (tls.js:430:15)
    at CleartextStream.Readable.read (_stream_readable.js:294:10)
    at EncryptedStream.write [as _write] (tls.js:344:25)
    at doWrite (_stream_writable.js:211:10)
    at writeOrBuffer (_stream_writable.js:201:5)
    at EncryptedStream.Writable.write (_stream_writable.js:172:11)
    at write (_stream_readable.js:547:24)

Server:

(function(){

    "use strict";

    var fs = require('fs');

    // you'll probably load configuration from config
    var cfg = {
        ssl: true,
        port: 8080,
        ssl_key: 'crt/server1.key',
        ssl_cert: 'crt/server1.crt'
    };

    var httpServ = require('https') 

    var WebSocketServer   = require('ws').Server;

    var app      = null;

    // dummy request processing
    var processRequest = function( req, res ) {

        res.writeHead(200);
        res.end("All glory to WebSockets!\n");
    };

    if ( cfg.ssl ) {

        app = httpServ.createServer({

            // providing server with  SSL key/cert
            key: fs.readFileSync( cfg.ssl_key ),
            cert: fs.readFileSync( cfg.ssl_cert ),
            //requestCert: true,
            //rejectUnauthorized: false

        }, processRequest ).listen( cfg.port );

    } else {

        app = httpServ.createServer( processRequest ).listen( cfg.port );
    }

    // passing or reference to web server so WS would knew port and SSL capabilities
    var wss = new WebSocketServer( { server: app } );


    wss.on( 'connection', function ( wsConnect ) {

        wsConnect.on( 'message', function ( message ) {

            console.log( message );

        });

    });


}());

Client:

var WebSocket = require('ws');
var ws = new WebSocket('wss://localhost:8080');
ws.on('open', function() {
    ws.send('something');
});

The certificate confirmed.

Help> please!

Yaroslav L.
  • 533
  • 2
  • 7
  • 16
  • check this http://stackoverflow.com/questions/17200391/nodejs-unable-to-verify-leaf-signature – vinayr Aug 27 '13 at 10:36

5 Answers5

20

I'm using a package called "superagent" and getting the same error. After trying several potential fixes, I came across this one that works for me 100% of the time:

process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0";

There's no need to do any requires or whatever : just add this to your code before your network calls and you're good to go.

dpjanes
  • 5,575
  • 3
  • 22
  • 27
  • 9
    This is a lousy idea. If the system has the proper CA root (AKA anchor) certificates, there should be a way to tell Node about them instead of turning off `strict-ssl`. – docwhat May 12 '14 at 20:30
  • 1
    "or do nothing and not be able to access the website because Node doesn't provide the right thing to do". – dpjanes May 13 '14 at 21:59
  • 3
    When [this bug](https://github.com/joyent/node/issues/7608) is fixed, you'll be able to do "The Right Thing(tm)". – docwhat May 15 '14 at 02:42
  • Worked for me. Eyes wide open that this is a bad idea for external sites. – Ryan Walls May 21 '14 at 15:15
  • 3
    Just giving out code without any explanation of what it does is not good. This might be a quickfix for internal services, but you should never do this in production. Leaves you wide open for a whole range of man in the middle attacks. – oligofren Dec 08 '15 at 12:20
11

The SSL certificate used by the server in your example is probably not fully trusted by the WebSocket client so NodeJS is throwing an error in its network library on the client-side.

You need to set rejectUnauthorized to false (this is an option that most high-level network libraries will allow you to set via an option that gets passed to the lower level NodeJS networking library).

I skimmed the ws module source code and looks like you should try this:

var ws = new WebSocket('wss://localhost:8080', null, {rejectUnauthorized: false});

NOTE: rejectUnauthorized should only be false during testing/development. Production applications should always use rejectUnauthorized: true for full security.

philidem
  • 311
  • 2
  • 7
2

If you do not want to disable your security. Add ca: [cert] option in http /socket client options. Where cert is Certificate of server you are connecting to or CA of the server you are connecting to.

Shrey
  • 559
  • 4
  • 14
  • 2
    Pointers or examples? – docwhat May 12 '14 at 20:31
  • https.globalAgent.options.ca = https.globalAgent.options.ca.concat(THE_SERVER_CA_YOU_WANT_TO_TRUST); – Shrey May 15 '14 at 03:19
  • You can also look at https://groups.google.com/forum/#!msg/nodejs/AjkHSYmiGYs/1LfNHbMhd48J , which promotes the node module ssl-root-cas which does the same thing of adding custom CAs to the list of ca certs the node trusts by default. – Shrey May 15 '14 at 03:21
  • There's a [ssl-root-cas](https://github.com/coolaj86/node-ssl-root-cas) module simplifying this for intermediary CAs, which the modern web browsers trust, as mentioned in [other post here](http://stackoverflow.com/a/22263280/623816). – Ferdinand Prantl Aug 31 '14 at 10:14
0

I've encountered a similar problem before, you may try to use https.globalAgent.options.secureProtocol = 'SSLv3_method' to set SSLv3 connection for https.

Rix
  • 1,466
  • 12
  • 19
0

As per the nginx official website, they clearly mentioned certificate should be the combination of The server certificate and chained certificates.MoreInfo

enter image description here

Sharathi RB
  • 787
  • 2
  • 8
  • 24