Last active
May 2, 2024 18:02
-
-
Save yurynix/0f48b39a3261109253c2528e127565bc to your computer and use it in GitHub Desktop.
Connect to serveo.net with ssh2 lib in nodejs
This file contains 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
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}`); | |
}()); | |
This file contains 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
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