Skip to content

cannot use tls.TLSSocket created from net.Socket after first 'data' event #8752

@coolaj86

Description

@coolaj86

tried on node v6.3 and v6.6

My goal is to mux a socket to use either tcp or tls after inspecting the first packet to see if it's a hello.

The problem I have is that I could not pass the socket to tls.TLSSocket (or tls.Server, or https.Server) after the 'data' event (even though I replay it) and have it emit data.

issue-8752.js:

//
//
// SETUP
//
//
'use strict';

var net = require('net');
var tls = require('tls');
var http = require('http');
var tlsOpts = {
  key: require('fs').readFileSync('./privkey.pem')
, cert: require('fs').readFileSync('./fullchain.pem')
};
var httpServer = http.createServer(function (req, res) {
  res.end('Hello, World!');
});
var tcp3000 = net.createServer();

tcp3000.listen(3000, function () {
  console.log('listening on 3000');
});



tcp3000.on('connection', function (socket) {
  console.log('connection incoming');
  // this works when I put it here, but I don't know if it's tls yet here
  // httpsServer.emit('connection', socket);

  socket.once('data', function (chunk) {
    console.log('data incoming');

    if (/http\/1/i.test(chunk.toString())) {

      console.log("looks like http, continue");

      // this works as expected
      httpServer.emit('connection', socket);

    } else {

      //**********************************************************
      //
      // PROBLEM
      //
      //**********************************************************
      console.log("doesn't look like http, try tls");

      // none of these methods work:
      // httpsServer.emit('connection', socket);  // this didn't work
      // tlsServer.emit('connection', socket);    // this didn't work either
      var tlsSocket = new tls.TLSSocket(socket, { secureContext: tls.createSecureContext(tlsOpts) });
      tlsSocket.on('data', function (chunk) {
        // never called
        console.log('chunk', chunk);
      });

    }

    // replay first packet
    socket.emit('data', chunk);
    // I've also tried this, which didn't work at all:
    // socket.unshift(chunk);
    // socket.emit('readable');
  });

});
curl https://local.test.ppl.family
connection incoming
data incoming
looks like http, continue
curl: (35) gnutls_handshake() failed: An unexpected TLS packet was received.

From the documentation I've found I don't think I'm doing anything wrong and the same process works with a plain tcp socket, so it makes me wonder if there isn't something amiss in the internals.

Also, the following does work (even though it's useless):

'use strict';

var net = require('net');
var http = require('http');
var https = require('https');
var tlsOpts = {
  key: require('fs').readFileSync('./privkey.pem')
, cert: require('fs').readFileSync('./fullchain.pem')
};
var httpServer = http.createServer(function (req, res) {
  res.end('Hello, World!');
});
var httpsServer = https.createServer(tlsOpts, function (req, res) {
  res.end('Hello, Encrypted World!');
});
var tcp3000 = net.createServer();

tcp3000.listen(3000, function () {
  console.log('listening on 3000');
});



tcp3000.on('connection', function (socket) {
  // if I never let the 'data' event fire, it works as expected.
  httpsServer.emit('connection', socket);
});

Metadata

Metadata

Assignees

No one assigned

    Labels

    streamIssues and PRs related to the stream subsystem.tlsIssues and PRs related to the tls subsystem.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions