146 lines
4.3 KiB
JavaScript
146 lines
4.3 KiB
JavaScript
// app/socket.js
|
|
"use strict";
|
|
|
|
const debug = require("debug");
|
|
const debugWebSSH2 = require("debug")("WebSSH2");
|
|
const SSH = require("ssh2").Client;
|
|
|
|
module.exports = function (io) {
|
|
io.on("connection", (socket) => {
|
|
let conn = null;
|
|
let stream = null;
|
|
console.log(`SOCKET CONNECT: ${socket.id}`);
|
|
|
|
// Remove existing listeners to prevent duplicates
|
|
socket.removeAllListeners("authenticate");
|
|
socket.removeAllListeners("data");
|
|
socket.removeAllListeners("resize");
|
|
socket.removeAllListeners("disconnect");
|
|
|
|
// Authenticate user
|
|
socket.on("authenticate", (credentials) => {
|
|
console.log(`SOCKET AUTHENTICATE: ${socket.id}`);
|
|
if (isValidCredentials(credentials)) {
|
|
console.log(`SOCKET AUTHENTICATE SUCCESS: ${socket.id}`);
|
|
initializeConnection(socket, credentials);
|
|
} else {
|
|
console.log(`SOCKET AUTHENTICATE FAILED: ${socket.id}`);
|
|
socket.emit("auth_result", {
|
|
success: false,
|
|
message: "Invalid credentials",
|
|
});
|
|
}
|
|
});
|
|
|
|
socket.on("disconnect", (reason) => {
|
|
debugWebSSH2(`SOCKET DISCONNECT: ${socket.id}, Reason: ${reason}`);
|
|
if (conn) {
|
|
conn.end();
|
|
}
|
|
// Clean up listeners
|
|
socket.removeAllListeners();
|
|
});
|
|
|
|
socket.on("data", (data) => {
|
|
if (stream) {
|
|
stream.write(data);
|
|
}
|
|
});
|
|
|
|
socket.on("resize", (data) => {
|
|
if (stream) {
|
|
stream.setWindow(data.rows, data.cols);
|
|
}
|
|
});
|
|
|
|
function initializeConnection(socket, credentials) {
|
|
if (conn) {
|
|
// If there's an existing connection, end it before creating a new one
|
|
conn.end();
|
|
}
|
|
|
|
conn = new SSH();
|
|
|
|
conn.on("ready", () => {
|
|
console.log(
|
|
`WebSSH2 Login: user=${credentials.username} from=${socket.handshake.address} host=${credentials.host} port=${credentials.port} sessionID=${socket.id}`
|
|
);
|
|
|
|
socket.emit("auth_result", { success: true });
|
|
socket.emit("allowreauth", true);
|
|
socket.emit("allowreplay", true);
|
|
socket.emit("title", `ssh://${credentials.host}`);
|
|
socket.emit("status", "SSH CONNECTION ESTABLISHED");
|
|
socket.emit("statusBackground", "green");
|
|
|
|
conn.shell(
|
|
{
|
|
term: credentials.term,
|
|
cols: credentials.cols,
|
|
rows: credentials.rows
|
|
},
|
|
(err, str) => {
|
|
if (err) {
|
|
return SSHerror("EXEC ERROR", err);
|
|
}
|
|
stream = str;
|
|
|
|
stream.on("data", (data) => {
|
|
socket.emit("data", data.toString("utf-8"));
|
|
});
|
|
|
|
stream.on("close", (code, signal) => {
|
|
SSHerror("STREAM CLOSE", {
|
|
message:
|
|
code || signal
|
|
? `CODE: ${code} SIGNAL: ${signal}`
|
|
: undefined,
|
|
});
|
|
});
|
|
|
|
stream.stderr.on("data", (data) => {
|
|
console.log("STDERR: " + data);
|
|
});
|
|
}
|
|
);
|
|
});
|
|
|
|
conn.on("banner", (data) => {
|
|
socket.emit("data", data.replace(/\r?\n/g, "\r\n"));
|
|
});
|
|
|
|
conn.on("end", () => SSHerror("CONN END BY HOST"));
|
|
conn.on("close", () => SSHerror("CONN CLOSE"));
|
|
conn.on("error", (err) => SSHerror("CONN ERROR", err));
|
|
|
|
conn.connect({
|
|
host: credentials.host,
|
|
port: credentials.port,
|
|
username: credentials.username,
|
|
password: credentials.password,
|
|
tryKeyboard: true,
|
|
algorithms: credentials.algorithms,
|
|
readyTimeout: credentials.readyTimeout,
|
|
keepaliveInterval: credentials.keepaliveInterval,
|
|
keepaliveCountMax: credentials.keepaliveCountMax,
|
|
debug: debug("ssh2")
|
|
});
|
|
}
|
|
|
|
function SSHerror(myFunc, err) {
|
|
const errorMessage = err ? `: ${err.message}` : "";
|
|
console.log(`WebSSH2 error: ${myFunc}${errorMessage}`);
|
|
socket.emit("ssherror", `SSH ${myFunc}${errorMessage}`);
|
|
if (conn) {
|
|
conn.end();
|
|
}
|
|
// Don't disconnect the socket here, let the client handle reconnection if necessary
|
|
// socket.disconnect(true);
|
|
}
|
|
|
|
function isValidCredentials(credentials) {
|
|
// Implement your credential validation logic here
|
|
return credentials && credentials.username && credentials.password;
|
|
}
|
|
});
|
|
};
|