Socket
Socket
Sign inDemoInstall

stunnel

Package Overview
Dependencies
19
Maintainers
4
Versions
17
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 0.9.6 to 0.9.7

4

package.json
{
"name": "stunnel",
"version": "0.9.6",
"version": "0.9.7",
"description": "A pure-JavaScript tunnel client for http and https similar to localtunnel.me, but uses TLS (SSL) with ServerName Indication (SNI) over https to work even in harsh network conditions such as in student dorms and behind HOAs, corporate firewalls, public libraries, airports, airplanes, etc. Can also tunnel tls and plain tcp.",

@@ -54,4 +54,4 @@ "main": "wsclient.js",

"tunnel-packer": "^1.1.0",
"ws": "^1.1.1"
"ws": "^2.2.3"
}
}

@@ -33,2 +33,8 @@ <!-- BANNER_TPL_BEGIN -->

```bash
npm install -g 'git+https://git@git.daplie.com/Daplie/node-tunnel-client.git#v1'
```
Or if you want to bow down to the kings of the centralized dictator-net:
```bash
npm install -g stunnel

@@ -35,0 +41,0 @@ ```

@@ -7,14 +7,68 @@ (function () {

var Packer = require('tunnel-packer');
var authenticated = false;
function run(copts) {
var tunnelUrl = copts.stunneld.replace(/\/$/, '') + '/?access_token=' + copts.token;
var activityTimeout = copts.activityTimeout || 2*60*1000;
var pongTimeout = copts.pongTimeout || 10*1000;
var wstunneler;
var authenticated = false;
var localclients = {};
// BaaS / Backendless / noBackend / horizon.io
// user authentication
// a place to store data
// file management
// Synergy Teamwork Paradigm = Jabberwocky
var handlers = {
var clientHandlers = {
onClose: function (cid, opts, err) {
wsHandlers.sendMessage(Packer.pack(opts, null, err && 'error' || 'end'));
delete localclients[cid];
console.log('[local onClose] closed "' + cid + '" (' + clientHandlers.count() + ' clients)');
}
, onError: function(cid, opts, err) {
console.info("[local onError] closing '" + cid + "' because '" + err.message + "'");
clientHandlers.onClose(cid, opts, err);
}
, closeSingle: function (cid) {
if (!localclients[cid]) {
return;
}
console.log('[closeSingle]', cid);
try {
localclients[cid].end();
setTimeout(function () {
if (localclients[cid]) {
console.warn('[closeSingle]', cid, 'connection still present');
delete localclients[cid];
}
}, 500);
} catch (err) {
console.warn('[closeSingle] failed to close connection', cid, err);
delete localclients[cid];
}
}
, closeAll: function () {
console.log('[closeAll]');
Object.keys(localclients).forEach(function (cid) {
try {
localclients[cid].end();
} catch (err) {
console.warn('[closeAll] failed to close connection', cid, err);
}
});
setTimeout(function () {
Object.keys(localclients).forEach(function (cid) {
if (localclients[cid]) {
console.warn('[closeAll]', cid, 'connection still present');
delete localclients[cid];
}
});
}, 500);
}
, count: function () {
return Object.keys(localclients).length;
}
};
var packerHandlers = {
onmessage: function (opts) {

@@ -38,3 +92,3 @@ var net = copts.net || require('net');

if (!portList) {
handlers._onLocalError(cid, opts, new Error("unsupported service '" + service + "'"));
packerHandlers._onConnectError(cid, opts, new Error("unsupported service '" + service + "'"));
return;

@@ -57,10 +111,7 @@ }

//console.warn(opts.data.toString());
handlers._onLocalError(cid, opts, new Error("missing servername for '" + cid + "' " + opts.data.byteLength));
packerHandlers._onConnectError(cid, opts, new Error("missing servername for '" + cid + "' " + opts.data.byteLength));
return;
}
port = portList[servername] || portList['*'];
console.info("[connect] new client '" + cid + "' for '" + servername + "' (" + (handlers._numClients() + 1) + " clients)");
console.log('port', port, opts.port, service, portList);
localclients[cid] = net.createConnection({

@@ -80,11 +131,4 @@ port: port

});
// 'data'
/*
localclients[cid].on('data', function (chunk) {
//console.log("[<=] local '" + opts.service + "' sent to '" + cid + "' <= ", chunk.byteLength, "bytes");
//console.log(JSON.stringify(chunk.toString()));
wstunneler.send(Packer.pack(opts, chunk), { binary: true });
});
//*/
///*
console.info("[connect] new client '" + cid + "' for '" + servername + "' (" + clientHandlers.count() + " clients)");
localclients[cid].on('readable', function (size) {

@@ -105,17 +149,9 @@ var chunk;

chunk = localclients[cid].read(size);
//console.log("[<=] local '" + opts.service + "' sent to '" + cid + "' <= ", chunk.byteLength, "bytes");
//console.log(JSON.stringify(chunk.toString()));
if (chunk) {
wstunneler.send(Packer.pack(opts, chunk), { binary: true });
wsHandlers.sendMessage(Packer.pack(opts, chunk));
}
} while (chunk);
});
//*/
localclients[cid].on('error', function (err) {
handlers._onLocalError(cid, opts, err);
});
localclients[cid].on('end', function () {
console.info("[end] closing client '" + cid + "' for '" + servername + "' (" + (handlers._numClients() - 1) + " clients)");
handlers._onLocalClose(cid, opts);
});
localclients[cid].on('error', clientHandlers.onError.bind(null, cid, opts));
localclients[cid].on('end', clientHandlers.onClose.bind(null, cid, opts));
}

@@ -125,3 +161,3 @@ , onend: function (opts) {

//console.log("[end] '" + cid + "'");
handlers._onend(cid);
clientHandlers.closeSingle(cid);
}

@@ -131,66 +167,71 @@ , onerror: function (opts) {

//console.log("[error] '" + cid + "'", opts.code || '', opts.message);
handlers._onend(cid);
clientHandlers.closeSingle(cid);
}
, _onend: function (cid) {
console.log('[_onend]');
if (localclients[cid]) {
try {
localclients[cid].end();
} catch(e) {
// ignore
}
}
delete localclients[cid];
, _onConnectError: function (cid, opts, err) {
console.info("[_onConnectError] opening '" + cid + "' failed because " + err.message);
wsHandlers.sendMessage(Packer.pack(opts, null, 'error'));
}
, _onLocalClose: function (cid, opts, err) {
console.log('[_onLocalClose]');
try {
wstunneler.send(Packer.pack(opts, null, err && 'error' || 'end'), { binary: true });
} catch(e) {
// ignore
}
delete localclients[cid];
}
, _onLocalError: function (cid, opts, err) {
console.info("[error] closing '" + cid + "' because '" + err.message + "' (" + (handlers._numClients() - 1) + " clients)");
handlers._onLocalClose(cid, opts, err);
}
, _numClients: function () {
return Object.keys(localclients).length;
}
};
var retry = true;
var lastActivity;
var timeoutId;
var wsHandlers = {
onOpen: function () {
console.info("[open] connected to '" + copts.stunneld + "'");
refreshTimeout: function () {
lastActivity = Date.now();
}
, checkTimeout: function () {
if (!wstunneler) {
console.warn('checkTimeout called when websocket already closed');
return;
}
// Determine how long the connection has been "silent", ie no activity.
var silent = Date.now() - lastActivity;
, retry: true
, closeClients: function () {
console.log('[close clients]');
Object.keys(localclients).forEach(function (cid) {
// If we have had activity within the last activityTimeout then all we need to do is
// call this function again at the soonest time when the connection could be timed out.
if (silent < activityTimeout) {
timeoutId = setTimeout(wsHandlers.checkTimeout, activityTimeout-silent);
}
// Otherwise we check to see if the pong has also timed out, and if not we send a ping
// and call this function again when the pong will have timed out.
else if (silent < activityTimeout + pongTimeout) {
console.log('pinging tunnel server');
try {
localclients[cid].end();
} catch(e) {
// ignore
wstunneler.ping();
} catch (err) {
console.warn('failed to ping tunnel server', err);
}
delete localclients[cid];
});
timeoutId = setTimeout(wsHandlers.checkTimeout, pongTimeout);
}
// Last case means the ping we sent before didn't get a response soon enough, so we
// need to close the websocket connection.
else {
console.log('connection timed out');
wstunneler.close(1000, 'connection timeout');
}
}
, onOpen: function () {
console.info("[open] connected to '" + copts.stunneld + "'");
wsHandlers.refreshTimeout();
timeoutId = setTimeout(wsHandlers.checkTimeout, activityTimeout);
}
, onClose: function () {
console.log('ON CLOSE');
console.log('ON CLOSE');
clearTimeout(timeoutId);
wstunneler = null;
clientHandlers.closeAll();
if (!authenticated) {
console.info('[close] failed on first attempt... check authentication.');
timeoutId = null;
}
else if (wsHandlers.retry) {
else if (retry) {
console.info('[retry] disconnected and waiting...');
setTimeout(run, 5000, copts);
timeoutId = setTimeout(connect, 5000);
}
else {
console.info('[close] closing tunnel to exit...');
}
process.removeListener('exit', wsHandlers.onExit);
process.removeListener('SIGINT', wsHandlers.onExit);
wsHandlers.closeClients();
}

@@ -203,6 +244,55 @@

, onExit: function () {
console.log('[wait] closing wstunneler...');
wsHandlers.retry = false;
wsHandlers.closeClients();
, sendMessage: function (msg) {
if (wstunneler) {
try {
wstunneler.send(msg, {binary: true});
} catch (err) {
console.warn('[sendMessage] error sending websocket message', err);
}
}
}
};
function connect() {
if (!retry) {
return;
}
timeoutId = null;
var machine = require('tunnel-packer').create(packerHandlers);
console.info("[connect] '" + copts.stunneld + "'");
wstunneler = new WebSocket(tunnelUrl, { rejectUnauthorized: !copts.insecure });
wstunneler.on('open', wsHandlers.onOpen);
wstunneler.on('close', wsHandlers.onClose);
wstunneler.on('error', wsHandlers.onError);
// Our library will automatically handle sending the pong respose to ping requests.
wstunneler.on('ping', wsHandlers.refreshTimeout);
wstunneler.on('pong', wsHandlers.refreshTimeout);
wstunneler.on('message', function (data, flags) {
wsHandlers.refreshTimeout();
if (data.error || '{' === data[0]) {
console.log(data);
return;
}
machine.fns.addChunk(data, flags);
});
}
connect();
function sigHandler() {
console.log('SIGINT');
// We want to handle cleanup properly unless something is broken in our cleanup process
// that prevents us from exitting, in which case we want the user to be able to send
// the signal again and exit the way it normally would.
process.removeListener('SIGINT', sigHandler);
retry = false;
if (timeoutId) {
clearTimeout(timeoutId);
timeoutId = null;
}
if (wstunneler) {
try {

@@ -213,32 +303,6 @@ wstunneler.close();

console.error(e);
// ignore
}
}
};
var machine = require('tunnel-packer').create(handlers);
console.info("[connect] '" + copts.stunneld + "'");
wstunneler = new WebSocket(tunnelUrl, { rejectUnauthorized: !copts.insecure });
wstunneler.on('open', wsHandlers.onOpen);
wstunneler.on('message', function (data, flags) {
if (data.error || '{' === data[0]) {
console.log(data);
return;
}
machine.fns.addChunk(data, flags);
});
wstunneler.on('close', wsHandlers.onClose);
wstunneler.on('error', wsHandlers.onError);
process.on('beforeExit', function (x) {
console.log('[beforeExit] event loop closing?', x);
});
process.on('exit', function (x) {
console.log('[exit] loop closed', x);
//wsHandlers.onExit(x);
});
process.on('SIGINT', function (x) {
console.log('SIGINT');
wsHandlers.onExit(x);
});
}
process.on('SIGINT', sigHandler);
}

@@ -245,0 +309,0 @@

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc