Re: Question about node v0.8.9, client certificates, and websockets....

979 views
Skip to first unread message

Manny Figudore

unread,
Sep 26, 2012, 11:28:50 PM9/26/12
to nod...@googlegroups.com
So after much debugging, giving up, then trying with the Faye package for node - I have a working example. I had to mod Faye to get tls.connect the certs but it does work with rejectUnauthorized:true.

On Wednesday, September 26, 2012 12:43:02 PM UTC-4, Manny Figudore wrote:
All,

I was playing with Node's ability to do client certification verification on https requests and this seems to work great. However, if I try to use ws, websocket, or socket.io/socket.io client (had to hack in a mod to pass the certificates in the client) and enable "rejectUnauthorized: true" - none of them can establish a websocket connection. The websocket modules all fail with either a "socket hung up" and/or a "ECONNRESET". With Chrome and the certs loaded - I can get a response from the https engine just fine. Below is my samples from my ws test bed:

-node v0.8.9
-Windows 7 x64
-native extensions complied successfully

server.js
var https = require('https')
    , WebSocketServer = require('ws').Server
    , fs = require('fs')

var options = {
    passphrase: 'password',
    key: fs.readFileSync('ssl/server-key.pem'),
    cert: fs.readFileSync('ssl/server-cert.pem'),
    ca:     [fs.readFileSync('ssl/ca1-cert.pem')],
    requestCert:        true,
    rejectUnauthorized: true
};
options.agent = new https.Agent(options);

var app = https.createServer(options, ServerAuthHandler);
app.listen(443);

var wss = new WebSocketServer({server: app});
wss.on('connection', function(ws) {
    var id = setInterval(function() {
        ws.send(JSON.stringify(process.memoryUsage()), function() { /* ignore errors */ });
    }, 100);
    console.log('started client interval');

    ws.on('close', function() {
        console.log('stopping client interval');
        clearInterval(id);
    });

    ws.on('message', function(message) {
        console.log('received: %s', message);
    });
});


/////////////
//Handler functions
/////////////
function ServerAuthHandler (req, res) {
    if (req.client.authorized) {
        res.writeHead(200, {"Content-Type": "application/json"});
        res.end('{"status":"approved"}');
        console.log('client was authorized!');
    } else {
        res.writeHead(401, {"Content-Type": "application/json"});
        console.log('request denied',req);
        res.end('{"status":"denied"}');
    }
}

client.js
 
var WebSocket = require('ws')
    , fs = require('fs');

var options = {
    passphrase: 'password'
    , key: fs.readFileSync("ssl/agent1-key.pem")
    , cert: fs.readFileSync("ssl/agent1-cert.pem")
    //, ca: [fs.readFileSync("ssl/ca1-cert.pem")]
};

var ws = new WebSocket('https://localhost',options);

ws.on('open', function() {
    ws.send('something');
});

ws.on('message', function(data, flags) {
    // flags.binary will be set if a binary data is received
    // flags.masked will be set if the data was masked
    console.log(data);
});

error output from client.js
"C:\Program Files\nodejs\node.exe" --debug-brk=10610 client.js
debugger listening on port 10610

events.js:66
        throw arguments[1]; // Unhandled 'error' event
                       ^
Error: socket hang up
    at SecurePair.error (tls.js:917:15)
    at EncryptedStream.CryptoStream._done (tls.js:395:17)
    at EncryptedStream.CryptoStream._pull (tls.js:546:12)
    at SecurePair.cycle (tls.js:835:20)
    at EncryptedStream.CryptoStream.end (tls.js:368:13)
    at Socket.onend (stream.js:66:10)
    at Socket.EventEmitter.emit (events.js:115:20)
    at TCP.onread (net.js:417:51)

Process finished with exit code 1


Some debugging seems to point to a possible issue inside of TLS.js where the SSL mod is throwing a "SSL routines:SSL3_GET_CLIENT_CERTIFICATE:peer did not return a certificate" - but I'm not sure if this is a node issue or just a matter of handing the https upgrade request properly inside of the websocket engines? Also - I noticed that secureEstablished is set to false when the above error is thrown.

Finally - setting rejectUnathorized:false allows this and the other samples to work fine - however - I want to ensure client certificate authentication throughout so this isnt really an option for my testing.

Any ideas?

Thanks,

Manny

 

James Coglan

unread,
Sep 27, 2012, 1:57:05 AM9/27/12
to nod...@googlegroups.com
On 27 September 2012 04:28, Manny Figudore <madscien...@gmail.com> wrote:
So after much debugging, giving up, then trying with the Faye package for node - I have a working example. I had to mod Faye to get tls.connect the certs but it does work with rejectUnauthorized:true.

I maintain Faye, can you show me what you did? Our mailing list is http://groups.google.com/group/faye-users 

Manny Figudore

unread,
Sep 27, 2012, 11:08:37 AM9/27/12
to nod...@googlegroups.com
I was going to get you a pull request last night but it was late. Work will have me busy until this afternoon but I will try to get you a pull tonight.
Reply all
Reply to author
Forward
0 new messages