This commit is contained in:
AJ ONeal 2018-04-28 19:25:46 -06:00
parent 727d06c5d8
commit 74e7cc0fc7
3 changed files with 87 additions and 25 deletions

View File

@ -77,11 +77,14 @@ Where `input.json` looks something like this:
} }
``` ```
Raw TCP SNI Packet
------------------
and `sni.tcp.bin` is any captured tcp packet, such as this one with a tls hello: and `sni.tcp.bin` is any captured tcp packet, such as this one with a tls hello:
`sni.tcp.bin`: `sni.tcp.bin`:
``` ```
0 1 2 3 4 5 6 7 8 9 A B C D D F 0 1 2 3 4 5 6 7 8 9 A B C D D F
0000000 16 03 01 00 c2 01 00 00 be 03 03 57 e3 76 50 66 0000000 16 03 01 00 c2 01 00 00 be 03 03 57 e3 76 50 66
0000010 03 df 99 76 24 c8 31 e6 e8 08 34 6b b4 7b bb 2c 0000010 03 df 99 76 24 c8 31 e6 e8 08 34 6b b4 7b bb 2c
0000020 f3 17 aa 5c ec 09 da da 83 5a b2 00 00 56 00 ff 0000020 f3 17 aa 5c ec 09 da da 83 5a b2 00 00 56 00 ff
@ -98,14 +101,18 @@ and `sni.tcp.bin` is any captured tcp packet, such as this one with a tls hello:
00000c7 00000c7
``` ```
Tunneled TCP SNI Packet
-----------------------
You should see that the result is simply all of the original packet with a leading header. You should see that the result is simply all of the original packet with a leading header.
Note that `16 03 01 00` starts at the 29th byte (at index 28 or 0x1C) instead of at index 0: Note that `16 03 01 00` starts at the 29th byte (at index 28 or 0x1C) instead of at index 0:
``` ```
0 1 2 3 4 5 6 7 8 9 A B C D D F 0 1 2 3 4 5 6 7 8 9 A B C D D F
0000000 fe 1a 49 50 76 34 2c 31 32 37 2e 30 2e 31 2e 31 <-- 0xfe = v1, 0x1a = 26 more bytes for header 0000000 fe 1a 49 50 76 34 2c 31 32 37 2e 30 2e 31 2e 31 <-- 0xfe = v1, 0x1a = 26 more bytes for header
0000010 2c 34 34 33 2c 31 39 39 2c 66 6f 6f 16 03 01 00 <-- first 4 bytes of tcp packet 0000010 2c 34 34 33 2c 31 39 39 2c 66 6f 6f
16 03 01 00 <-- first 4 bytes of tcp packet
0000020 c2 01 00 00 be 03 03 57 e3 76 50 66 03 df 99 76 0000020 c2 01 00 00 be 03 03 57 e3 76 50 66 03 df 99 76
0000030 24 c8 31 e6 e8 08 34 6b b4 7b bb 2c f3 17 aa 5c 0000030 24 c8 31 e6 e8 08 34 6b b4 7b bb 2c f3 17 aa 5c
0000040 ec 09 da da 83 5a b2 00 00 56 00 ff c0 24 c0 23 0000040 ec 09 da da 83 5a b2 00 00 56 00 ff c0 24 c0 23

View File

@ -226,24 +226,30 @@ Packer.pack = function (address, data, service) {
return buf; return buf;
}; };
function extractSocketProp(socket, propName) {
// remoteAddress, remotePort... ugh... https://github.com/nodejs/node/issues/8854
var value = socket[propName] || socket['_' + propName];
try {
value = value || socket._handle._parent.owner.stream[propName];
} catch (e) {}
try {
value = value || socket._handle._parentWrap[propName];
value = value || socket._handle._parentWrap._handle.owner.stream[propName];
} catch (e) {}
return value || '';
}
Packer.socketToAddr = function (socket) { Packer.socketToAddr = function (socket) {
// TODO BUG XXX // TODO BUG XXX
// https://github.com/nodejs/node/issues/8854 // https://github.com/nodejs/node/issues/8854
// tlsSocket.remoteAddress = remoteAddress; // causes core dump // tlsSocket.remoteAddress = remoteAddress; // causes core dump
// console.log(tlsSocket.remoteAddress); // console.log(tlsSocket.remoteAddress);
function extractValue(name) {
return socket[name]
|| socket['_'+name]
|| socket._handle._parentWrap[name]
|| socket._handle._parentWrap._handle.owner.stream[name]
;
}
return { return {
family: extractValue('remoteFamily') family: extractSocketProp(socket, 'remoteFamily')
, address: extractValue('remoteAddress') , address: extractSocketProp(socket, 'remoteAddress')
, port: extractValue('remotePort') , port: extractSocketProp(socket, 'remotePort')
}; };
}; };
@ -262,6 +268,53 @@ Packer.socketToId = function (socket) {
* *
*/ */
var addressNames = [
'remoteAddress'
, 'remotePort'
, 'remoteFamily'
, 'localAddress'
, 'localPort'
];
// Imporoved workaround for https://github.com/nodejs/node/issues/8854
// Unlike Duplex this should handle all of the events needed to make everything work.
Packer.wrapSocket = function (socket) {
var myDuplex = new require('stream').Duplex();
addressNames.forEach(function (name) {
myDuplex[name] = extractSocketProp(socket, name);
});
// Handle everything needed for the write part of the Duplex. We need to overwrite the
// `end` function because there is no other way to know when the other side calls it.
myDuplex._write = socket.write.bind(socket);
myDuplex.end = socket.end.bind(socket);
// Handle everything needed for the read part of the Duplex. See the example under
// https://nodejs.org/api/stream.html#stream_readable_push_chunk_encoding.
myDuplex._read = function () {
socket.resume();
};
socket.on('data', function (chunk) {
if (!myDuplex.push(chunk)) {
socket.pause();
}
});
socket.on('end', function () {
myDuplex.push(null);
});
// Handle the the things not directly related to reading or writing
socket.on('error', function (err) {
console.error('[error] wrapped socket errored - ' + err.toString());
myDuplex.emit('error', err);
});
socket.on('close', function () {
myDuplex.emit('close');
});
myDuplex.destroy = socket.destroy.bind(socket);
return myDuplex;
};
var Transform = require('stream').Transform; var Transform = require('stream').Transform;
var util = require('util'); var util = require('util');
@ -274,23 +327,20 @@ function MyTransform(options) {
Transform.call(this, options); Transform.call(this, options);
} }
util.inherits(MyTransform, Transform); util.inherits(MyTransform, Transform);
function transform(me, data, encoding, callback) {
var address = me.__my_addr;
address.service = address.service || me.__my_service;
me.push(Packer.pack(address, data));
callback();
}
MyTransform.prototype._transform = function (data, encoding, callback) { MyTransform.prototype._transform = function (data, encoding, callback) {
return transform(this, data, encoding, callback); var address = this.__my_addr;
address.service = address.service || this.__my_service;
this.push(Packer.pack(address, data));
callback();
}; };
Packer.Stream = {}; Packer.Stream = {};
var Dup = { var Dup = {
write: function (chunk, encoding, cb) { write: function (chunk, encoding, cb) {
//console.log('_write', chunk.byteLength); //console.log('_write', chunk.byteLength);
this.__my_socket.write(chunk, encoding); this.__my_socket.write(chunk, encoding, cb);
cb();
} }
, read: function (size) { , read: function (size) {
//console.log('_read'); //console.log('_read');
@ -302,6 +352,11 @@ var Dup = {
} }
}; };
Packer.Stream.create = function (socket) { Packer.Stream.create = function (socket) {
if (!Packer.Stream.warned) {
console.warn('`Stream.create` deprecated, use `wrapSocket` instead');
Packer.Stream.warned = true;
}
// Workaround for // Workaround for
// https://github.com/nodejs/node/issues/8854 // https://github.com/nodejs/node/issues/8854

View File

@ -1,6 +1,6 @@
{ {
"name": "tunnel-packer", "name": "tunnel-packer",
"version": "1.2.1", "version": "1.3.1",
"description": "A strategy for packing and unpacking a proxy stream (i.e. packets through a tunnel). Handles multiplexed and tls connections. Used by telebit and telebitd.", "description": "A strategy for packing and unpacking a proxy stream (i.e. packets through a tunnel). Handles multiplexed and tls connections. Used by telebit and telebitd.",
"main": "index.js", "main": "index.js",
"scripts": { "scripts": {