cp dines
This commit is contained in:
parent
9c0ba04b31
commit
9df8e1097e
3 changed files with 322 additions and 176 deletions
|
@ -1,114 +1,203 @@
|
|||
/* eslint-disable complexity */
|
||||
/* eslint no-unused-expressions: ["error", { "allowShortCircuit": true, "allowTernary": true }],
|
||||
no-console: ["error", { allow: ["warn", "error"] }] */
|
||||
/* jshint esversion: 6, asi: true, node: true */
|
||||
// socket.js
|
||||
|
||||
// private
|
||||
const debug = require('debug');
|
||||
const debugWebSSH2 = require('debug')('WebSSH2');
|
||||
const SSH = require('ssh2').Client;
|
||||
const CIDRMatcher = require('cidr-matcher');
|
||||
const validator = require('validator');
|
||||
const dnsPromises = require('dns').promises;
|
||||
const util = require('util');
|
||||
const { webssh2debug, auditLog, logError } = require('./logging');
|
||||
const { Client } = require('ssh2');
|
||||
const tls = require('tls');
|
||||
const forge = require('node-forge');
|
||||
|
||||
/**
|
||||
* parse conn errors
|
||||
* @param {object} socket Socket object
|
||||
* @param {object} err Error object
|
||||
*/
|
||||
function connError(socket, err) {
|
||||
let msg = util.inspect(err);
|
||||
const { session } = socket.request;
|
||||
if (err?.level === 'client-authentication') {
|
||||
msg = `Authentication failure user=${session.username} from=${socket.handshake.address}`;
|
||||
socket.emit('allowreauth', session.ssh.allowreauth);
|
||||
socket.emit('reauth');
|
||||
}
|
||||
if (err?.code === 'ENOTFOUND') {
|
||||
msg = `Host not found: ${err.hostname}`;
|
||||
}
|
||||
if (err?.level === 'client-timeout') {
|
||||
msg = `Connection Timeout: ${session.ssh.host}`;
|
||||
}
|
||||
logError(socket, 'CONN ERROR', msg);
|
||||
function convertPKCS8toPKCS1(pkcs8Key) {
|
||||
const privateKeyInfo = forge.pki.privateKeyFromPem(pkcs8Key);
|
||||
|
||||
// Convert the private key to PKCS#1 format
|
||||
const pkcs1Pem = forge.pki.privateKeyToPem(privateKeyInfo);
|
||||
|
||||
return pkcs1Pem;
|
||||
}
|
||||
|
||||
/**
|
||||
* check ssh host is in allowed subnet
|
||||
* @param {object} socket Socket information
|
||||
*/
|
||||
async function checkSubnet(socket) {
|
||||
let ipaddress = socket.request.session.ssh.host;
|
||||
if (!validator.isIP(`${ipaddress}`)) {
|
||||
try {
|
||||
const result = await dnsPromises.lookup(socket.request.session.ssh.host);
|
||||
ipaddress = result.address;
|
||||
} catch (err) {
|
||||
logError(
|
||||
socket,
|
||||
'CHECK SUBNET',
|
||||
`${err.code}: ${err.hostname} user=${socket.request.session.username} from=${socket.handshake.address}`
|
||||
);
|
||||
socket.emit('ssherror', '404 HOST IP NOT FOUND');
|
||||
socket.disconnect(true);
|
||||
return;
|
||||
}
|
||||
}
|
||||
const conn = new Client();
|
||||
|
||||
const matcher = new CIDRMatcher(socket.request.session.ssh.allowedSubnets);
|
||||
if (!matcher.contains(ipaddress)) {
|
||||
logError(
|
||||
socket,
|
||||
'CHECK SUBNET',
|
||||
`Requested host ${ipaddress} outside configured subnets / REJECTED user=${socket.request.session.username} from=${socket.handshake.address}`
|
||||
);
|
||||
socket.emit('ssherror', '401 UNAUTHORIZED');
|
||||
socket.disconnect(true);
|
||||
}
|
||||
// Function to create a TLS connection (simulating ProxyCommand with openssl s_client)
|
||||
const proxyConnect = (hostname, callback) => {
|
||||
const tlsSocket = tls.connect(
|
||||
{
|
||||
host: 'ssh.runloop.pro', // Proxy server address
|
||||
port: 443, // Proxy port (HTTPS over TLS)
|
||||
servername: hostname, // Target hostname, acts like -servername in openssl
|
||||
checkServerIdentity: () => {
|
||||
return undefined;
|
||||
}, // Disable hostname validation
|
||||
},
|
||||
() => {
|
||||
console.log('TLS connection established');
|
||||
callback(null, tlsSocket); // Return the established socket
|
||||
},
|
||||
);
|
||||
|
||||
tlsSocket.on('error', (err) => {
|
||||
console.error('TLS connection error:', err);
|
||||
callback(err);
|
||||
});
|
||||
};
|
||||
|
||||
// Main function to establish the SSH connection over the TLS proxy
|
||||
function establishConnection() {
|
||||
proxyConnect(
|
||||
'devbox-0191bab8-397a-742e-8100-138b1ee3a99e.e81c0643-9165-4d39-b4e8-ccd8d22214dd.ssh.runloop.pro',
|
||||
(err, tlsSocket) => {
|
||||
if (err) {
|
||||
console.error('Error during proxy connection:', err);
|
||||
return;
|
||||
}
|
||||
|
||||
// Now use ssh2 to connect over the TLS socket
|
||||
conn
|
||||
.on('ready', () => {
|
||||
console.log('SSH Client ready');
|
||||
// conn.exec("uptime", (err, stream) => {
|
||||
// if (err) throw err;
|
||||
// stream
|
||||
// .on("close", (code, signal) => {
|
||||
// console.log(
|
||||
// "Stream :: close :: code: " + code + ", signal: " + signal
|
||||
// );
|
||||
// conn.end();
|
||||
// })
|
||||
// .on("data", (data) => {
|
||||
// console.log("STDOUT: " + data);
|
||||
// })
|
||||
// .stderr.on("data", (data) => {
|
||||
// console.log("STDERR: " + data);
|
||||
// });
|
||||
// });
|
||||
})
|
||||
.on('error', (err) => {
|
||||
console.error('SSH Connection error:', err);
|
||||
})
|
||||
.connect({
|
||||
sock: tlsSocket, // Pass the TLS socket as the connection
|
||||
username: 'user', // Replace with the correct SSH username
|
||||
privateKey: convertPKCS8toPKCS1(
|
||||
'-----BEGIN RSA PRIVATE KEY-----\nMIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQC8lJC0JKQJZ+Md\n2tqnpkO5Vlptmxuh3RE+ilBNKNKkDYqAPfRGgoYs9QI73QXWH4hsGd9+9wYGWvFe\n0tkDSv4fs0Ps1daIQ4h+JPvNes2ieBoCVw68D4f+LrTorY6H5PuJQM5Kdau0buzL\nO/4wIsb9QDEeDmF/ZWcFgE2YkP7B/AGvjU17EDU7299awlEo40KsIRlJ/5KcH9B2\nTvwe2YSVXGS84gb2tmwG4zUh8CjvT3GIP6fMeCdCs40+vn1maryQzFZmm2A4WIt2\nunwObvTcBJbgn77dwbPxQm5BlZRuIevgeE5Cb0qEVoriRAdDQTnug0LrTRLKRAIS\nqlLg6uGxAgMBAAECggEABUdZV5mQ9+xvCJZoOXoneignJttJJjpEcc44WjiS0OHK\nJzXUwSaFL/v5wIg60hgW3wPIZErw4buo9wEK7xMp0uRXOelwdGcDiphpbgKKgApB\nnCAouu3qXhyblsnI7BfmTJzCSYZKtKXIPhYjUuCeVld2KIO5ifHiNN63DVa9sttZ\nM4ZRUUT1ujN+TXRGEM0EFOeJwtD+e/AJD97QIj4IkQ4cMpL/7n83uw1N/WyXTcXf\nscVPEsGLIj7MmGzvjJAhHoLckshQC1+Kfo2KTuoACYQxgPoPCAtLMivhd3ea9Q3g\n0BeU5bfhepOgBOyiRXG14ks0j/t25cfTslusmgrMAwKBgQDOX/ecMub3t/qm/cX7\nJzQNXs/Ru9alfoBIhURWQ271LN9drmG6GfAE5/qdlPAKxantuj2an4eMdROwOHzK\nw+YzIMChyaxtX5Z3EWOyKTqTOD/+nmDvlMZdnWFXbUTDc4FqCGEkTk7+oYX/D6aB\nit2hdnyTAYs/9HPhiF5nllinUwKBgQDp7TN5GhJa3hEDwthCmVx5ED+sZhL5rz0C\nr9IPjoCQypDO3O8rgtDWTXFXvuCeN2/dBnRc2SAQ9a8YplA22zgKFLbrJ/BMaQnT\nWoTtshZQ0moYaNJPcfag/Y7yOCbkkCzXQFjkasXFt4pXIvktg+v1ILoGnaFTZOM/\nkFCrWSsGawKBgQChEtgAyt3odGknEyUGLIf884ZCjVgv3PclIxa+OW2N4JMJ3EQc\na4ghXCoH+ioMTlCd4mGYoHC8WNigDsafv5yZRTP0UqLIzvVyQ1lLwdAc/ac9BMJl\n2/mjMWW7ReaIoktcxeOD4bbYGJusArwTmZ34GrGKT4cuyI31dmkwcnEJTwKBgHAH\nUzFaFRRDaW6dr6glfi3UZEoSEGBXVialQTqGCnhNKpCHKltyKMWZDQDyvuvGrOHz\nJ2MX8M1ue86YR64dyna5eOihleliHHyFy0dylFFck8bg3GeDspNjG0RRM/8eNPtZ\nK7kokVKhFbWpYCA2H5ijdbOZZhtkI5jbambFK1/FAoGBAJ7bpFWdiUaobInBSD5n\neCGGRJKKgA305gBcDr0G0Quo2AcZFzRUF+k27DXpK2zBq9H2vR8nLjNLvvaWFcJE\n4gzHEGriaXrZq4sxvihYgKXU12Buoz3UDtS51eArefr+QCr+ikPb8LdViwI29/W0\n+R1hc2PNxjd1mX+oxNamYV/l\n-----END RSA PRIVATE KEY-----\n',
|
||||
), // Replace with the path to your private key
|
||||
hostHash: 'md5', // Optional: Match host keys by hash
|
||||
strictHostKeyChecking: false, // Disable strict host key checking
|
||||
});
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
// var fs = require('fs')
|
||||
// var hostkeys = JSON.parse(fs.readFileSync('./hostkeyhashes.json', 'utf8'))
|
||||
let termCols;
|
||||
let termRows;
|
||||
|
||||
// public
|
||||
module.exports = function appSocket(socket) {
|
||||
let login = false;
|
||||
|
||||
socket.once('disconnecting', (reason) => {
|
||||
webssh2debug(socket, `SOCKET DISCONNECTING: ${reason}`);
|
||||
if (login === true) {
|
||||
auditLog(
|
||||
socket,
|
||||
`LOGOUT user=${socket.request.session.username} from=${socket.handshake.address} host=${socket.request.session.ssh.host}:${socket.request.session.ssh.port}`
|
||||
);
|
||||
login = false;
|
||||
}
|
||||
});
|
||||
|
||||
async function setupConnection() {
|
||||
// if websocket connection arrives without an express session, kill it
|
||||
if (!socket.request.session) {
|
||||
socket.emit('401 UNAUTHORIZED');
|
||||
webssh2debug(socket, 'SOCKET: No Express Session / REJECTED');
|
||||
debugWebSSH2('SOCKET: No Express Session / REJECTED');
|
||||
socket.disconnect(true);
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Error handling for various events. Outputs error to client, logs to
|
||||
* server, destroys session and disconnects socket.
|
||||
* @param {string} myFunc Function calling this function
|
||||
* @param {object} err error object or error message
|
||||
*/
|
||||
// eslint-disable-next-line complexity
|
||||
function SSHerror(myFunc, err) {
|
||||
let theError;
|
||||
if (socket.request.session) {
|
||||
// we just want the first error of the session to pass to the client
|
||||
const firstError = socket.request.session.error || (err ? err.message : undefined);
|
||||
theError = firstError ? `: ${firstError}` : '';
|
||||
// log unsuccessful login attempt
|
||||
if (err && err.level === 'client-authentication') {
|
||||
console.error(
|
||||
`WebSSH2 ${'error: Authentication failure'.red.bold} user=${socket.request.session.username.yellow.bold.underline} from=${socket.handshake.address.yellow.bold.underline}`,
|
||||
);
|
||||
socket.emit('allowreauth', socket.request.session.ssh.allowreauth);
|
||||
socket.emit('reauth');
|
||||
} else {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(
|
||||
`WebSSH2 Logout: user=${socket.request.session.username} from=${socket.handshake.address} host=${socket.request.session.ssh.host} port=${socket.request.session.ssh.port} sessionID=${socket.request.sessionID}/${socket.id} allowreplay=${socket.request.session.ssh.allowreplay} term=${socket.request.session.ssh.term}`,
|
||||
);
|
||||
if (err) {
|
||||
theError = err ? `: ${err.message}` : '';
|
||||
console.error(`WebSSH2 error${theError}`);
|
||||
}
|
||||
}
|
||||
socket.emit('ssherror', `SSH ${myFunc}${theError}`);
|
||||
socket.request.session.destroy();
|
||||
socket.disconnect(true);
|
||||
} else {
|
||||
theError = err ? `: ${err.message}` : '';
|
||||
socket.disconnect(true);
|
||||
}
|
||||
debugWebSSH2(`SSHerror ${myFunc}${theError}`);
|
||||
}
|
||||
// If configured, check that requsted host is in a permitted subnet
|
||||
if (socket.request.session?.ssh?.allowedSubnets?.length > 0) {
|
||||
checkSubnet(socket);
|
||||
if (
|
||||
(((socket.request.session || {}).ssh || {}).allowedSubnets || {}).length &&
|
||||
socket.request.session.ssh.allowedSubnets.length > 0
|
||||
) {
|
||||
let ipaddress = socket.request.session.ssh.host;
|
||||
if (!validator.isIP(`${ipaddress}`)) {
|
||||
try {
|
||||
const result = await dnsPromises.lookup(socket.request.session.ssh.host);
|
||||
ipaddress = result.address;
|
||||
} catch (err) {
|
||||
console.error(
|
||||
`WebSSH2 ${`error: ${err.code} ${err.hostname}`.red.bold} user=${
|
||||
socket.request.session.username.yellow.bold.underline
|
||||
} from=${socket.handshake.address.yellow.bold.underline}`,
|
||||
);
|
||||
socket.emit('ssherror', '404 HOST IP NOT FOUND');
|
||||
socket.disconnect(true);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
const matcher = new CIDRMatcher(socket.request.session.ssh.allowedSubnets);
|
||||
if (!matcher.contains(ipaddress)) {
|
||||
console.error(
|
||||
`WebSSH2 ${
|
||||
`error: Requested host ${ipaddress} outside configured subnets / REJECTED`.red.bold
|
||||
} user=${socket.request.session.username.yellow.bold.underline} from=${
|
||||
socket.handshake.address.yellow.bold.underline
|
||||
}`,
|
||||
);
|
||||
socket.emit('ssherror', '401 UNAUTHORIZED');
|
||||
socket.disconnect(true);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
const conn = new SSH();
|
||||
|
||||
// const conn = new SSH();
|
||||
socket.on('geometry', (cols, rows) => {
|
||||
termCols = cols;
|
||||
termRows = rows;
|
||||
});
|
||||
conn.on('banner', (data) => {
|
||||
// need to convert to cr/lf for proper formatting
|
||||
socket.emit('data', data.replace(/\r?\n/g, '\r\n').toString('utf-8'));
|
||||
});
|
||||
|
||||
conn.on('handshake', () => {
|
||||
socket.emit('setTerminalOpts', socket.request.session.ssh.terminal);
|
||||
conn.on('ready', () => {
|
||||
debugWebSSH2(
|
||||
`WebSSH2 Login: user=${socket.request.session.username} from=${socket.handshake.address} host=${socket.request.session.ssh.host} port=${socket.request.session.ssh.port} sessionID=${socket.request.sessionID}/${socket.id} mrhsession=${socket.request.session.ssh.mrhsession} allowreplay=${socket.request.session.ssh.allowreplay} term=${socket.request.session.ssh.term}`,
|
||||
);
|
||||
socket.emit('menu');
|
||||
socket.emit('allowreauth', socket.request.session.ssh.allowreauth);
|
||||
socket.emit('setTerminalOpts', socket.request.session.ssh.terminal);
|
||||
socket.emit('title', `ssh://${socket.request.session.ssh.host}`);
|
||||
if (socket.request.session.ssh.header.background)
|
||||
socket.emit('headerBackground', socket.request.session.ssh.header.background);
|
||||
|
@ -116,101 +205,88 @@ module.exports = function appSocket(socket) {
|
|||
socket.emit('header', socket.request.session.ssh.header.name);
|
||||
socket.emit(
|
||||
'footer',
|
||||
`ssh://${socket.request.session.username}@${socket.request.session.ssh.host}:${socket.request.session.ssh.port}`
|
||||
`ssh://${socket.request.session.username}@${socket.request.session.ssh.host}:${socket.request.session.ssh.port}`,
|
||||
);
|
||||
});
|
||||
|
||||
conn.on('ready', () => {
|
||||
webssh2debug(
|
||||
socket,
|
||||
`CONN READY: LOGIN: user=${socket.request.session.username} from=${socket.handshake.address} host=${socket.request.session.ssh.host} port=${socket.request.session.ssh.port} allowreplay=${socket.request.session.ssh.allowreplay} term=${socket.request.session.ssh.term}`
|
||||
);
|
||||
auditLog(
|
||||
socket,
|
||||
`LOGIN user=${socket.request.session.username} from=${socket.handshake.address} host=${socket.request.session.ssh.host}:${socket.request.session.ssh.port}`
|
||||
);
|
||||
login = true;
|
||||
socket.emit('status', 'SSH CONNECTION ESTABLISHED');
|
||||
socket.emit('statusBackground', 'green');
|
||||
socket.emit('allowreplay', socket.request.session.ssh.allowreplay);
|
||||
const { term, cols, rows } = socket.request.session.ssh;
|
||||
conn.shell({ term, cols, rows }, (err, stream) => {
|
||||
if (err) {
|
||||
logError(socket, `EXEC ERROR`, err);
|
||||
conn.end();
|
||||
socket.disconnect(true);
|
||||
return;
|
||||
}
|
||||
socket.once('disconnect', (reason) => {
|
||||
webssh2debug(socket, `CLIENT SOCKET DISCONNECT: ${util.inspect(reason)}`);
|
||||
conn.end();
|
||||
socket.request.session.destroy();
|
||||
});
|
||||
socket.on('error', (errMsg) => {
|
||||
webssh2debug(socket, `SOCKET ERROR: ${errMsg}`);
|
||||
logError(socket, 'SOCKET ERROR', errMsg);
|
||||
conn.end();
|
||||
socket.disconnect(true);
|
||||
});
|
||||
socket.on('control', (controlData) => {
|
||||
if (controlData === 'replayCredentials' && socket.request.session.ssh.allowreplay) {
|
||||
stream.write(`${socket.request.session.userpassword}\n`);
|
||||
}
|
||||
if (controlData === 'reauth' && socket.request.session.username && login === true) {
|
||||
auditLog(
|
||||
socket,
|
||||
`LOGOUT user=${socket.request.session.username} from=${socket.handshake.address} host=${socket.request.session.ssh.host}:${socket.request.session.ssh.port}`
|
||||
);
|
||||
login = false;
|
||||
conn.shell(
|
||||
{
|
||||
term: socket.request.session.ssh.term,
|
||||
cols: termCols,
|
||||
rows: termRows,
|
||||
},
|
||||
(err, stream) => {
|
||||
if (err) {
|
||||
SSHerror(`EXEC ERROR${err}`);
|
||||
conn.end();
|
||||
socket.disconnect(true);
|
||||
return;
|
||||
}
|
||||
webssh2debug(socket, `SOCKET CONTROL: ${controlData}`);
|
||||
});
|
||||
socket.on('resize', (data) => {
|
||||
stream.setWindow(data.rows, data.cols);
|
||||
webssh2debug(socket, `SOCKET RESIZE: ${JSON.stringify([data.rows, data.cols])}`);
|
||||
});
|
||||
socket.on('data', (data) => {
|
||||
stream.write(data);
|
||||
});
|
||||
stream.on('data', (data) => {
|
||||
socket.emit('data', data.toString('utf-8'));
|
||||
});
|
||||
stream.on('close', (code, signal) => {
|
||||
webssh2debug(socket, `STREAM CLOSE: ${util.inspect([code, signal])}`);
|
||||
if (socket.request.session?.username && login === true) {
|
||||
auditLog(
|
||||
socket,
|
||||
`LOGOUT user=${socket.request.session.username} from=${socket.handshake.address} host=${socket.request.session.ssh.host}:${socket.request.session.ssh.port}`
|
||||
);
|
||||
login = false;
|
||||
}
|
||||
if (code !== 0 && typeof code !== 'undefined')
|
||||
logError(socket, 'STREAM CLOSE', util.inspect({ message: [code, signal] }));
|
||||
socket.disconnect(true);
|
||||
conn.end();
|
||||
});
|
||||
stream.stderr.on('data', (data) => {
|
||||
console.error(`STDERR: ${data}`);
|
||||
});
|
||||
});
|
||||
socket.on('data', (data) => {
|
||||
stream.write(data);
|
||||
});
|
||||
socket.on('control', (controlData) => {
|
||||
switch (controlData) {
|
||||
case 'replayCredentials':
|
||||
if (socket.request.session.ssh.allowreplay) {
|
||||
stream.write(`${socket.request.session.userpassword}\n`);
|
||||
}
|
||||
/* falls through */
|
||||
default:
|
||||
debugWebSSH2(`controlData: ${controlData}`);
|
||||
}
|
||||
});
|
||||
socket.on('resize', (data) => {
|
||||
stream.setWindow(data.rows, data.cols);
|
||||
});
|
||||
socket.on('disconnecting', (reason) => {
|
||||
debugWebSSH2(`SOCKET DISCONNECTING: ${reason}`);
|
||||
});
|
||||
socket.on('disconnect', (reason) => {
|
||||
debugWebSSH2(`SOCKET DISCONNECT: ${reason}`);
|
||||
const errMsg = { message: reason };
|
||||
SSHerror('CLIENT SOCKET DISCONNECT', errMsg);
|
||||
conn.end();
|
||||
// socket.request.session.destroy()
|
||||
});
|
||||
socket.on('error', (errMsg) => {
|
||||
SSHerror('SOCKET ERROR', errMsg);
|
||||
conn.end();
|
||||
});
|
||||
|
||||
stream.on('data', (data) => {
|
||||
socket.emit('data', data.toString('utf-8'));
|
||||
});
|
||||
stream.on('close', (code, signal) => {
|
||||
const errMsg = {
|
||||
message:
|
||||
code || signal
|
||||
? (code ? `CODE: ${code}` : '') +
|
||||
(code && signal ? ' ' : '') +
|
||||
(signal ? `SIGNAL: ${signal}` : '')
|
||||
: undefined,
|
||||
};
|
||||
SSHerror('STREAM CLOSE', errMsg);
|
||||
conn.end();
|
||||
});
|
||||
stream.stderr.on('data', (data) => {
|
||||
console.error(`STDERR: ${data}`);
|
||||
});
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
conn.on('end', (err) => {
|
||||
if (err) logError(socket, 'CONN END BY HOST', err);
|
||||
webssh2debug(socket, 'CONN END BY HOST');
|
||||
socket.disconnect(true);
|
||||
SSHerror('CONN END BY HOST', err);
|
||||
});
|
||||
conn.on('close', (err) => {
|
||||
if (err) logError(socket, 'CONN CLOSE', err);
|
||||
webssh2debug(socket, 'CONN CLOSE');
|
||||
socket.disconnect(true);
|
||||
SSHerror('CONN CLOSE', err);
|
||||
});
|
||||
conn.on('error', (err) => connError(socket, err));
|
||||
|
||||
conn.on('keyboard-interactive', (_name, _instructions, _instructionsLang, _prompts, finish) => {
|
||||
webssh2debug(socket, 'CONN keyboard-interactive');
|
||||
conn.on('error', (err) => {
|
||||
SSHerror('CONN ERROR', err);
|
||||
});
|
||||
conn.on('keyboard-interactive', (name, instructions, instructionsLang, prompts, finish) => {
|
||||
debugWebSSH2("conn.on('keyboard-interactive')");
|
||||
finish([socket.request.session.userpassword]);
|
||||
});
|
||||
if (
|
||||
|
@ -219,18 +295,28 @@ module.exports = function appSocket(socket) {
|
|||
socket.request.session.ssh
|
||||
) {
|
||||
// console.log('hostkeys: ' + hostkeys[0].[0])
|
||||
const { ssh } = socket.request.session;
|
||||
ssh.username = socket.request.session.username;
|
||||
ssh.password = socket.request.session.userpassword;
|
||||
ssh.tryKeyboard = true;
|
||||
ssh.debug = debug('ssh2');
|
||||
conn.connect(ssh);
|
||||
// conn.connect({
|
||||
// host: socket.request.session.ssh.host,
|
||||
// port: socket.request.session.ssh.port,
|
||||
// localAddress: socket.request.session.ssh.localAddress,
|
||||
// localPort: socket.request.session.ssh.localPort,
|
||||
// username: socket.request.session.username,
|
||||
// password: socket.request.session.userpassword,
|
||||
// privateKey: socket.request.session.privatekey,
|
||||
// tryKeyboard: true,
|
||||
// algorithms: socket.request.session.ssh.algorithms,
|
||||
// readyTimeout: socket.request.session.ssh.readyTimeout,
|
||||
// keepaliveInterval: socket.request.session.ssh.keepaliveInterval,
|
||||
// keepaliveCountMax: socket.request.session.ssh.keepaliveCountMax,
|
||||
// debug: debug('ssh2'),
|
||||
// });
|
||||
console.log('EVAN HERE');
|
||||
establishConnection();
|
||||
} else {
|
||||
webssh2debug(
|
||||
socket,
|
||||
`CONN CONNECT: Attempt to connect without session.username/password or session varialbles defined, potentially previously abandoned client session. disconnecting websocket client.\r\nHandshake information: \r\n ${util.inspect(
|
||||
socket.handshake
|
||||
)}`
|
||||
debugWebSSH2(
|
||||
`Attempt to connect without session.username/password or session varialbles defined, potentially previously abandoned client session. disconnecting websocket client.\r\nHandshake information: \r\n ${JSON.stringify(
|
||||
socket.handshake,
|
||||
)}`,
|
||||
);
|
||||
socket.emit('ssherror', 'WEBSOCKET ERROR - Refresh the browser and try again');
|
||||
socket.request.session.destroy();
|
||||
|
@ -238,4 +324,5 @@ module.exports = function appSocket(socket) {
|
|||
}
|
||||
}
|
||||
setupConnection();
|
||||
// establishConnection();
|
||||
};
|
||||
|
|
57
package-lock.json
generated
Normal file
57
package-lock.json
generated
Normal file
|
@ -0,0 +1,57 @@
|
|||
{
|
||||
"name": "myssh",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"dependencies": {
|
||||
"node-forge": "^1.3.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"bun-types": "^1.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/node": {
|
||||
"version": "20.12.14",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.12.14.tgz",
|
||||
"integrity": "sha512-scnD59RpYD91xngrQQLGkE+6UrHUPzeKZWhhjBSa3HSkwjbQc38+q3RoIVEwxQGRw3M+j5hpNAM+lgV3cVormg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"undici-types": "~5.26.4"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/ws": {
|
||||
"version": "8.5.12",
|
||||
"resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.12.tgz",
|
||||
"integrity": "sha512-3tPRkv1EtkDpzlgyKyI8pGsGZAGPEaXeu0DOj5DI25Ja91bdAYddYHbADRYVrZMRbfW+1l5YwXVDKohDJNQxkQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/bun-types": {
|
||||
"version": "1.1.26",
|
||||
"resolved": "https://registry.npmjs.org/bun-types/-/bun-types-1.1.26.tgz",
|
||||
"integrity": "sha512-n7jDe62LsB2+WE8Q8/mT3azkPaatKlj/2MyP6hi3mKvPz9oPpB6JW/Ll6JHtNLudasFFuvfgklYSE+rreGvBjw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@types/node": "~20.12.8",
|
||||
"@types/ws": "~8.5.10"
|
||||
}
|
||||
},
|
||||
"node_modules/node-forge": {
|
||||
"version": "1.3.1",
|
||||
"resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz",
|
||||
"integrity": "sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==",
|
||||
"engines": {
|
||||
"node": ">= 6.13.0"
|
||||
}
|
||||
},
|
||||
"node_modules/undici-types": {
|
||||
"version": "5.26.5",
|
||||
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz",
|
||||
"integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,6 +1,8 @@
|
|||
{
|
||||
"dependencies": {},
|
||||
"dependencies": {
|
||||
"node-forge": "^1.3.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"bun-types": "^1.0.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue