coolaj86
coolaj86

Reputation: 77122

How to mux (intercept) net (tcp) sockets in node.js?

I want to look at headers on the first packet of a net socket connection and then decide what to do with it from there.

TCP Example (works, but useless)

This is useless because it doesn't solve my problem, it just demonstrates that, in theory, the problem is solvable.

'use strict';

var net = require('net');
var http = require('http');

var http80 = http.createServer(function (req, res) {
  res.end('Hello, World!');
});

var tcp80 = net.createServer(function (socket) {

  socket.once('data', function (chunk) {

    if (/http\/1/i.test(chunk.toString())) {
      console.log("looks like http, continue");
      http80.emit('connection', socket);
    } else {
      console.log("looks like tcp, die");
      socket.end();
    }

    socket.pause();
    process.nextTick(function () {
      socket.emit('data', chunk);
      socket.resume();
    });
  });

});

tcp80.listen(80, function () {
  console.log('listening on 80');
});

TLS Example (doesn't work)

This is what I'm actually trying to do, but doesn't work:

'use strict';

var net = require('net');
var sni = require('sni');
var https = require('https');
var tlsOpts = require('localhost.daplie.com-certificates').merge({});

var https443 = https.createServer(tlsOpts, function (req, res) {
  res.end('Hello, Encrypted World!');
});

var tcp443 = net.createServer(function (socket) {

  // looking at the first packet, this is the gold
  socket.once('data', function (chunk) {

    // undo the read, more or less
    socket.pause();
    process.nextTick(function () {
      socket.emit('data', chunk);
      socket.resume();
    });

    if (/^tcp\.example\.com/i.test(sni(chunk))) {
      console.log("TODO: handle as raw tls / tcp");
      return;
    }

    console.log("handling as https");
    https443.emit('connection', socket);
  });

});

tcp443.listen(443, function () {
  console.log('listening on 443');
});

I've tried manually emitting the readable event as well as manually emitting the data event with the chunk and resumeing, but it just seems to hang in all of those cases rather than working like in the example above.

Upvotes: 1

Views: 697

Answers (0)

Related Questions