Skip to content

Instantly share code, notes, and snippets.

@brandon-lockaby
Last active March 1, 2022 21:55
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 3 You must be signed in to fork a gist
  • Save brandon-lockaby/2020839 to your computer and use it in GitHub Desktop.
Save brandon-lockaby/2020839 to your computer and use it in GitHub Desktop.
node.js tcp proxy
var net = require("net");
var Proxy = function() {
};
Proxy.to = function(dst_host, dst_port) {
var proxy = new Proxy();
proxy.dstHost = dst_host;
proxy.dstPort = dst_port;
proxy.mid = [];
return proxy;
};
Proxy.prototype.use = function(fn) {
this.mid.push(fn);
return this;
}
Proxy.prototype._handle = function(buf, src, dst, out) {
var evt = {
"buf": buf,
"src": src,
"dst": dst,
"out": out
};
var next = Proxy.nop;
for(var i = this.mid.length - 1; i >= 0; i--) {
next = this.mid[i].bind(this, evt, next);
}
next();
return this;
};
Proxy.prototype.listen = function(port) {
var self = this;
this.server = net.createServer(function (sockA) {
console.log("sockA " + sockA.address().address + ":" + sockA.address().port);
var preb = [];
sockA.on("data", pre = function(data) {
preb.push(data);
});
var sockB = net.connect(self.dstPort, self.dstHost, function() {
console.log("sockB " + sockB.address().address + ":" + sockB.address().port);
sockA.removeListener("data", pre);
while(preb.length) {
self._handle(preb.shift(), sockA, sockB, true);
}
sockA.on("data", function(buf) {
self._handle(buf, sockA, sockB, true);
});
sockB.on("data", function(buf) {
self._handle(buf, sockB, sockA, false);
});
sockA.on("end", function() {
console.log("sockA end");
sockB.removeAllListeners();
sockB.end();
});
sockB.on("end", function() {
console.log("sockB end");
sockA.removeAllListeners();
sockA.end();
});
});
});
this.server.listen(port, function() {
// hello I am listening
});
return this;
};
// built-in middlewares
Proxy.nop = function() {
};
Proxy.send = function(evt, next) {
evt.dst.write(evt.buf);
next();
};
Proxy.consoleLogMeta = function(evt, next) {
console.log(
(evt.out ? "\x1B[35m" : "\x1B[33m")
+ evt.src.remoteAddress + ":" + evt.src.remotePort
+ " ——> "
+ evt.dst.remoteAddress + ":" + evt.dst.remotePort
+ " —— " + evt.buf.length + " bytes"
+ "\x1B[0m"
);
next();
};
Proxy.consoleLogString = function(evt, next) {
console.log(evt.buf.toString());
next();
};
Proxy.consoleLogBuffer = function(evt, next) {
var i = 0;
while(i + 16 < evt.buf.length) {
console.log(evt.buf.slice(i, i + 16));
i += 16;
}
if(i < evt.buf.length) console.log(evt.buf.slice(i));
next();
};
Proxy.consoleLogSnippet = function(evt, next) {
var str = evt.buf.toString();
var i;
var ellip = false;
i = str.indexOf("\n"); if(i != -1) {
str = str.substr(0, i);
ellip = true;
}
i = str.indexOf("\r"); if(i != -1) {
str = str.substr(0, i);
ellip = true;
}
var rows = 80; //process.binding('stdio').getRows();
if(str.length > rows) {
str = str.substr(0, rows);
ellip = true;
}
if(ellip) {
str += "…";
}
console.log(str);
next();
};
module.exports = Proxy;
/* Usage:
var Proxy = require("./lib/proxy");
Proxy.to("test.com", 80)
.use(Proxy.consoleLogMeta)
.use(Proxy.send)
.listen(8080);
*/
@4mo1
Copy link

4mo1 commented Sep 18, 2012

Hey Brandon, thanks for this proxy. It worked for me on node 0.6.8, but not on node 0.8.8. Trying to see if anything has changed in the net module, but thought of letting you know.

@brandon-lockaby
Copy link
Author

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment