Skip to content

Instantly share code, notes, and snippets.

@yurynix
Last active May 2, 2024 18:02
Show Gist options
  • Save yurynix/0f48b39a3261109253c2528e127565bc to your computer and use it in GitHub Desktop.
Save yurynix/0f48b39a3261109253c2528e127565bc to your computer and use it in GitHub Desktop.
Connect to serveo.net with ssh2 lib in nodejs
const net = require('net');
const { Client } = require('ssh2');
function tunnel(localPort) {
const sshClient = new Client();
let resolvePromise = null;
let rejectPromise = null;
const resultPromise = new Promise((resolve, reject) => {
resolvePromise = resolve;
rejectPromise = reject;
});
sshClient.on('ready', () => {
console.log('SSH Client :: ready');
sshClient.forwardIn('localhost', 80, (err, port) => {
if (err) return rejectPromise(err);
console.log(`Forwarding ready ${port}!`);
});
sshClient.shell((err, stream) => {
if (err) return rejectPromise(err);
stream.on('close', () => {
console.log('sshClient shell stream :: close');
sshClient.end();
}).on('data', (data) => {
if (data) console.log(`ssh (${data.length}) >> ` + data);
// Extract URL if it appears in the data
const urlMatch = data.toString().match(/https:\/\/\S+/);
if (urlMatch) {
resolvePromise({
destroy: () => sshClient.destroy(),
url: urlMatch[0]
});
}
});
});
}).on('tcp connection', (info, accept, reject) => {
const remoteConnection = accept();
const localSocket = new net.Socket();
localSocket.connect(localPort, '127.0.0.1', (err) => {
if (err) throw err;
console.log(`Local socket connected to ${localPort} <- ${info.srcIP}:${info.srcPort}`, err);
localSocket.pipe(remoteConnection).pipe(localSocket);
});
}).connect({
host: 'serveo.net',
port: 22,
username: "johndoe",
tryKeyboard: true
});
return resultPromise;
}
(async function main() {
const { destroy, url } = await tunnel(8080);
setTimeout(() => {
console.log('DESTROYING!');
destroy();
}, 30 * 1000);
console.log(`Tunnel at ${url}`);
}());
let fs = require('fs'),
ssh2 = require('ssh2'),
http = require('http');
let proxyRequest = null;
const server = http.createServer((req, res) => {
proxyRequest(req, res);
});
server.listen(port, (err) => {
if (err) {
return console.log('something bad happened', err)
}
console.log(`HTTP server is listening on ${port}`)
})
function toRequestString(req) {
let requestString = `${req.method} ${req.url} HTTP/${req.httpVersion}\r\n`;
for (const [header, value] of Object.entries(req.headers)) {
requestString += `${header}: ${value}\r\n`;
}
requestString += '\r\n';
return requestString;
}
new ssh2.Server({
hostKeys: [fs.readFileSync('private.key')]
}, client => {
console.log('Client connected!');
client
.on('authentication', ctx => {
// if (
// ctx.method === 'password'
// && ctx.username === 'foo'
// && ctx.password === 'bar'
// ) {
// ctx.accept();
// } else {
// ctx.reject();
// }
ctx.accept();
})
.on('ready', () => {
console.log('Client authenticated!');
client
.on('session', (accept, reject) => {
let session = accept();
session.on('shell', function(accept, reject) {
const stream = accept();
stream.write('Hello my dear, im a fake serveo.net https://your-tunnel.yury.dev');
}).on('pty', function(accept, reject) {
accept();
});
})
.on('request', (accept, reject, name, info) => {
console.log('request', name, info);
if (name === 'tcpip-forward') {
accept();
proxyRequest = (req, res) => {
console.log(`Proxy request... ${info.bindAddr} ${info.bindPort}`);
client.forwardOut(
info.bindAddr, info.bindPort,
res.socket.remoteAddress, res.socket.remotePort,
(err, upstream) => {
if (err) {
req.end();
return console.error('not working: ' + err);
}
req.socket.pipe(upstream).pipe(res.socket);
upstream.write(Buffer.from(toRequestString(req)));
});
}
} else {
reject();
}
});
});
}).listen(22, '0.0.0.0', function() {
console.log('Listening on port ' + this.address().port);
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment