const { Server } = require('socket.io') const { Client: Client } = require('ssh2') const { readSSHRecord, verifyAuth, RSADecrypt, AESDecrypt } = require('../utils') function createTerminal(socket, vps) { vps.shell({ term: 'xterm-color' }, (err, stream) => { if (err) return socket.emit('output', err.toString()) stream .on('data', (data) => { socket.emit('output', data.toString()) }) .on('close', () => { console.log('关闭终端') vps.end() }) socket.on('input', key => { if(vps._sock.writable === false) return console.log('终端连接已关闭') stream.write(key) }) socket.emit('connect_terminal') socket.on('resize', ({ rows, cols }) => { stream.setWindow(rows, cols) }) }) } module.exports = (httpServer) => { const serverIo = new Server(httpServer, { path: '/terminal', cors: { origin: '*' } }) serverIo.on('connection', (socket) => { // 前者兼容nginx反代, 后者兼容nodejs自身服务 let clientIp = socket.handshake.headers['x-forwarded-for'] || socket.handshake.address let vps = new Client() console.log('terminal websocket 已连接') socket.on('create', ({ host: ip, token }) => { const { code } = verifyAuth(token, clientIp) if(code !== 1) { socket.emit('token_verify_fail') socket.disconnect() return } // console.log('code:', code) const sshRecord = readSSHRecord() let loginInfo = sshRecord.find(item => item.host === ip) if(!sshRecord.some(item => item.host === ip)) return socket.emit('create_fail', `未找到【${ ip }】凭证`) let { type, host, port, username, randomKey } = loginInfo try { // 解密放到try里面,防止报错【公私钥必须配对, 否则需要重新添加服务器密钥】 randomKey = AESDecrypt(randomKey) // 先对称解密key randomKey = RSADecrypt(randomKey) // 再非对称解密key loginInfo[type] = AESDecrypt(loginInfo[type], randomKey) // 对称解密ssh密钥 console.log('准备连接服务器:', host) vps .on('ready', () => { console.log('已连接到服务器:', host) socket.emit('connect_success', `已连接到服务器:${ host }`) createTerminal(socket, vps) }) .on('error', (err) => { console.log('连接失败:', err.level) socket.emit('connect_fail', err.message) }) .connect({ type: 'privateKey', host, port, username, [type]: loginInfo[type] // debug: (info) => { // console.log(info) // } }) } catch (err) { console.log('创建失败:', err.message) socket.emit('create_fail', err.message) } }) socket.on('disconnect', (reason) => { console.log('终端连接断开:', reason) vps.end() vps.destroy() vps = null }) }) }