sshception/lib/ssh.js

116 lines
No EOL
4.2 KiB
JavaScript

import { Client } from 'ssh2';
import ssh2Protocols from 'ssh2/lib/protocol/constants.js';
const
{
SUPPORTED_KEX,
SUPPORTED_CIPHER,
SUPPORTED_SERVER_HOST_KEY,
SUPPORTED_MAC,
SUPPORTED_COMPRESSION
} = ssh2Protocols,
algorithms = {
kex: SUPPORTED_KEX,
cipher: SUPPORTED_CIPHER,
serverHostKey: SUPPORTED_SERVER_HOST_KEY,
hmac: SUPPORTED_MAC,
compress: SUPPORTED_COMPRESSION
};
export const
chainedSession = ({
hostsChain,
isTest,
command
}) => new Promise((
onReady,
onError
) => {
const clients = [];
(async () => {
for(let i = 0; i < hostsChain.length; i++){
const
prevClient = clients[i-1],
{
address,
port,
username,
password
} = hostsChain[i],
nextHost = hostsChain[i+1],
client = clients[i] = new Client();
client.on('error', onError);
await new Promise(resolve => {
client.on('ready', () => {
if(nextHost) resolve();
else {
if(isTest){
client.end();
onReady();
}
else if(command) client.exec(
command,
{
pty: {
term: 'xterm-256color'
}
},
(error, stream) => {
if(error) return onError(error);
onReady({
stream,
end: () => client.end()
});
}
);
else client.shell(
{ term: 'xterm-256color' },
(error, stream) => {
if(error) return onError(error);
onReady({
stream,
end: () => client.end()
});
}
);
}
});
(async () => {
let prevClientStream;
if(prevClient){
client.on('end', () => prevClient.end());
prevClientStream = await new Promise(resolve => prevClient.forwardOut(
'127.0.0.1',
12345 + i,
address,
port,
(
error,
prevClientStream
) => {
if(error) onError(error);
resolve(prevClientStream);
}
));
}
try {
client.connect({
...prevClientStream ? {
sock: prevClientStream
} : {
host: address,
port
},
username,
password,
algorithms
});
}
catch(error){
onError(error);
}
})();
});
}
})();
});