-
-
Save root-ali/0ceed88c7579bf255b90fa4280950781 to your computer and use it in GitHub Desktop.
A basic TCP proxy written in node.js with dynamic remote host
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env node | |
const net = require('net'); | |
process.on('uncaughtException', function(error) { | |
console.error(error); | |
}); | |
const localPortHttp = process.argv[2]; | |
const localPortHttps = process.argv[3]; | |
let server = net.createServer(function(localsocket) { | |
const remoteSocket = new net.Socket(); | |
const obj = { count: 0 }; | |
// remoteSocket.connect(remotePort, remoteHost); | |
localsocket.on('connect', function(data) { | |
console.log('>>> connection #%d from %s:%d', | |
server.connections, | |
localsocket.remoteAddress, | |
localsocket.remotePort, | |
); | |
}); | |
localsocket.on('data', function(data) { | |
console.log('%s:%d - writing data to remote', | |
localsocket.remoteAddress, | |
localsocket.remotePort, | |
); | |
if (obj.count === 0) { | |
let host = data.toString().replace(/\r?\n|\r/g, " ").split(":")[1].split(" ")[1]; | |
remoteSocket.connect(localPortHttp, host); | |
obj.count++; | |
} | |
let flushed = remoteSocket.write(data); | |
if (!flushed) { | |
console.log(' remote not flushed; pausing local'); | |
localsocket.pause(); | |
} | |
}); | |
remoteSocket.on('data', function(data) { | |
console.log('%s:%d - writing data to local', | |
localsocket.remoteAddress, | |
localsocket.remotePort, | |
); | |
console.log('send to local:', data.toString()); | |
let flushed = localsocket.write(data); | |
if (!flushed) { | |
console.log(' local not flushed; pausing remote'); | |
remoteSocket.pause(); | |
} | |
}); | |
localsocket.on('drain', function() { | |
console.log('%s:%d - resuming remote', | |
localsocket.remoteAddress, | |
localsocket.remotePort, | |
); | |
remoteSocket.resume(); | |
}); | |
remoteSocket.on('drain', function() { | |
console.log('%s:%d - resuming local', | |
localsocket.remoteAddress, | |
localsocket.remotePort, | |
); | |
localsocket.resume(); | |
}); | |
localsocket.on('close', function(had_error) { | |
console.log('%s:%d - closing remote', | |
localsocket.remoteAddress, | |
localsocket.remotePort, | |
); | |
remoteSocket.end(); | |
}); | |
remoteSocket.on('close', function(had_error) { | |
console.log('%s:%d - closing local', | |
localsocket.remoteAddress, | |
localsocket.remotePort, | |
); | |
localsocket.end(); | |
}); | |
}); | |
let serverHttps = net.createServer(function(localsocket) { | |
const remoteSocket = new net.Socket(); | |
const obj = { count: 0 }; | |
localsocket.on('connect', function(data) { | |
console.log('>>> connection #%d from %s:%d', | |
server.connections, | |
localsocket.remoteAddress, | |
localsocket.remotePort, | |
); | |
}); | |
localsocket.on('data', function(data) { | |
console.log('%s:%d - writing data to remote', | |
localsocket.remoteAddress, | |
localsocket.remotePort, | |
); | |
if (obj.count === 0) { | |
let host = data.toString().replace(/[^\x20-\x7E]/g, '').replace(/[^.,1-9a-z ]/g, ' ').split(' '); | |
host = longest_string(host); | |
remoteSocket.connect(localPortHttps, host[0]); | |
obj.count++; | |
} | |
let flushed = remoteSocket.write(data); | |
if (!flushed) { | |
console.log(' remote not flushed; pausing local'); | |
localsocket.pause(); | |
} | |
}); | |
remoteSocket.on('data', function(data) { | |
console.log('%s:%d - writing data to local', | |
localsocket.remoteAddress, | |
localsocket.remotePort, | |
); | |
console.log('send to local:', data.toString()); | |
let flushed = localsocket.write(data); | |
if (!flushed) { | |
console.log(' local not flushed; pausing remote'); | |
remoteSocket.pause(); | |
} | |
}); | |
localsocket.on('drain', function() { | |
console.log('%s:%d - resuming remote', | |
localsocket.remoteAddress, | |
localsocket.remotePort, | |
); | |
remoteSocket.resume(); | |
}); | |
remoteSocket.on('drain', function() { | |
console.log('%s:%d - resuming local', | |
localsocket.remoteAddress, | |
localsocket.remotePort, | |
); | |
localsocket.resume(); | |
}); | |
localsocket.on('close', function(had_error) { | |
console.log('%s:%d - closing remote', | |
localsocket.remoteAddress, | |
localsocket.remotePort, | |
); | |
remoteSocket.end(); | |
}); | |
remoteSocket.on('close', function(had_error) { | |
console.log('%s:%d - closing local', | |
localsocket.remoteAddress, | |
localsocket.remotePort, | |
); | |
localsocket.end(); | |
}); | |
}); | |
function longest_string(str_ara) { | |
var max = str_ara[0].length; | |
str_ara.map(v => max = Math.max(max, v.length)); | |
result = str_ara.filter(v => v.length == max); | |
return result; | |
} | |
server.listen(localPortHttp , '0.0.0.0'); | |
serverHttps.listen(localPortHttps , '0.0.0.0'); | |
console.log('redirecting connections from 0.0.0.0:%d and 0.0.0.0:%s', localPortHttp , localPortHttps); | |
// For running the proxy execute this: | |
// ./proxy.js 80 443 | |
// This would run proxy on port 80 and 443 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment