mirror of
https://github.com/chaos-zhu/easynode.git
synced 2026-10-06 15:13:18 +08:00
feat: 优化rdp连接
This commit is contained in:
@@ -0,0 +1,28 @@
|
||||
const { createProxyMiddleware } = require('http-proxy-middleware')
|
||||
|
||||
/**
|
||||
* RDP代理中间件
|
||||
* 将/rdp-proxy/guac路径的请求代理到RDP独立端口
|
||||
*/
|
||||
const createRdpProxyMiddleware = () => {
|
||||
const RDP_PORT = process.env.RDP_PORT || 8083
|
||||
const RDP_HOST = process.env.RDP_HOST || '127.0.0.1' // 使用127.0.0.1更可靠
|
||||
const target = `http://${ RDP_HOST }:${ RDP_PORT }`
|
||||
|
||||
console.log('Creating RDP proxy middleware with target:', target)
|
||||
|
||||
// 创建WebSocket代理
|
||||
const wsProxy = createProxyMiddleware({
|
||||
target: target,
|
||||
ws: true,
|
||||
changeOrigin: true,
|
||||
pathRewrite: {
|
||||
'^/rdp-proxy': ''
|
||||
},
|
||||
logLevel: 'debug'
|
||||
})
|
||||
|
||||
return wsProxy
|
||||
}
|
||||
|
||||
module.exports = createRdpProxyMiddleware
|
||||
@@ -0,0 +1,48 @@
|
||||
const http = require('http')
|
||||
const GuacamoleLite = require('guacamole-lite')
|
||||
|
||||
const RDP_PORT = process.env.RDP_PORT || 8083 // 使用独立端口
|
||||
const GUACD_HOST = process.env.GUACD_HOST || 'guacd'
|
||||
const GUACD_PORT = Number(process.env.GUACD_PORT) || 4822
|
||||
|
||||
// 创建独立的HTTP服务器用于RDP
|
||||
const rdpServer = http.createServer()
|
||||
|
||||
const websocketOptions = {
|
||||
server: rdpServer,
|
||||
path: '/guac'
|
||||
}
|
||||
|
||||
const guacdOptions = {
|
||||
host: GUACD_HOST,
|
||||
port: GUACD_PORT
|
||||
}
|
||||
|
||||
const clientOptions = {
|
||||
crypt: {
|
||||
cypher: 'AES-256-CBC',
|
||||
key: global.rpdToken || Array.from({ length:32 },()=>Math.random().toString(36)[2]).join('')
|
||||
}
|
||||
}
|
||||
|
||||
const startRdpServer = () => {
|
||||
try {
|
||||
const guacamole = new GuacamoleLite(websocketOptions, guacdOptions, clientOptions)
|
||||
|
||||
guacamole.on('connection', () => {
|
||||
consola.success('✔ RDP guacamole连接成功')
|
||||
})
|
||||
|
||||
guacamole.on('error', (err) => {
|
||||
consola.error('❌ RDP guacamole连接错误', err)
|
||||
})
|
||||
|
||||
rdpServer.listen(RDP_PORT, () => {
|
||||
consola.success(`RDP服务运行在端口: ${ RDP_PORT }`)
|
||||
})
|
||||
} catch (error) {
|
||||
consola.error('❌ RDP 初始化失败:', error.message)
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = { startRdpServer }
|
||||
+17
-2
@@ -3,7 +3,7 @@ const compose = require('koa-compose') // 组合中间件,简化写法
|
||||
const http = require('http')
|
||||
const { httpPort } = require('./config')
|
||||
const middlewares = require('./middlewares')
|
||||
const wsRdp = require('./socket/rdp')
|
||||
const { startRdpServer } = require('./rdp-server')
|
||||
const wsTerminal = require('./socket/terminal')
|
||||
const wsSftpV2 = require('./socket/sftp-v2')
|
||||
const wsDocker = require('./socket/docker')
|
||||
@@ -15,17 +15,32 @@ const { throwError } = require('./utils/tools')
|
||||
const httpServer = () => {
|
||||
const app = new Koa()
|
||||
const server = http.createServer(app.callback())
|
||||
|
||||
// 添加RDP WebSocket代理
|
||||
const createRdpProxyMiddleware = require('./middlewares/rdp-proxy')
|
||||
const rdpProxy = createRdpProxyMiddleware()
|
||||
|
||||
// 只处理WebSocket升级请求的代理(RDP只需要WebSocket)
|
||||
server.on('upgrade', (request, socket, head) => {
|
||||
if (request.url.startsWith('/rdp-proxy')) {
|
||||
rdpProxy.upgrade(request, socket, head)
|
||||
}
|
||||
})
|
||||
|
||||
serverHandler(app, server)
|
||||
|
||||
// ws一直报跨域的错误:参照官方文档使用createServer API创建服务
|
||||
server.listen(httpPort, () => {
|
||||
consola.success(`Server(http) is running on: http://localhost:${ httpPort }`)
|
||||
})
|
||||
|
||||
// 启动独立的RDP服务
|
||||
startRdpServer()
|
||||
}
|
||||
|
||||
// 服务
|
||||
function serverHandler(app, server) {
|
||||
app.proxy = true // 用于nginx反代时获取真实客户端ip
|
||||
wsRdp(server) // RDP
|
||||
wsTerminal(server) // 终端
|
||||
wsSftpV2(server) // sftp-v2
|
||||
wsDocker(server) // docker
|
||||
|
||||
@@ -1,40 +0,0 @@
|
||||
const GuacamoleLite = require('guacamole-lite')
|
||||
|
||||
const GUACD_HOST = process.env.GUACD_HOST || 'guacd'
|
||||
const GUACD_PORT = Number(process.env.GUACD_PORT) || 4822
|
||||
|
||||
const getOptions = (server) => {
|
||||
const websocketOptions = {
|
||||
server,
|
||||
path: '/guac'
|
||||
}
|
||||
|
||||
const guacdOptions = {
|
||||
host: GUACD_HOST,
|
||||
port: GUACD_PORT
|
||||
}
|
||||
|
||||
const clientOptions = {
|
||||
crypt: {
|
||||
cypher: 'AES-256-CBC',
|
||||
key: global.rpdToken
|
||||
}
|
||||
}
|
||||
return { websocketOptions, guacdOptions, clientOptions }
|
||||
}
|
||||
module.exports = (httpServer) => {
|
||||
const { websocketOptions, guacdOptions, clientOptions } = getOptions(httpServer)
|
||||
let guacamole = new GuacamoleLite(websocketOptions, guacdOptions, clientOptions)
|
||||
try {
|
||||
guacamole.on('connection', () => {
|
||||
consola.success('✔ RDP guacamole连接成功')
|
||||
})
|
||||
guacamole.on('error', (err) => {
|
||||
consola.error('❌ RDP guacamole连接错误', err)
|
||||
})
|
||||
} catch (error) {
|
||||
guacamole.close()
|
||||
guacamole = null
|
||||
consola.error('❌ RDP 初始化失败:', error.message)
|
||||
}
|
||||
}
|
||||
@@ -29,6 +29,7 @@
|
||||
"fs-extra": "^11.2.0",
|
||||
"global": "^4.4.0",
|
||||
"guacamole-lite": "^1.2.0",
|
||||
"http-proxy-middleware": "^3.0.5",
|
||||
"iconv-lite": "^0.6.3",
|
||||
"jsonwebtoken": "^9.0.2",
|
||||
"koa": "2.16.2",
|
||||
|
||||
@@ -371,7 +371,7 @@ const getRdpWsUrl = async () => {
|
||||
const { data } = await $api.getRdpToken({ hostId: hostId.value, width, height })
|
||||
if (!data) return $message.error('获取RDP WS URL失败')
|
||||
const wsHost = $isDev ? `ws://${ location.hostname }:8082` : location.origin.replace('http', 'ws')
|
||||
return `${ wsHost }/guac?token=${ encodeURIComponent(data) }`
|
||||
return `${ wsHost }/rdp-proxy/guac?token=${ encodeURIComponent(data) }`
|
||||
}
|
||||
|
||||
const connectRdp = async () => {
|
||||
|
||||
@@ -1278,6 +1278,13 @@
|
||||
resolved "https://registry.yarnpkg.com/@types/http-errors/-/http-errors-2.0.4.tgz#7eb47726c391b7345a6ec35ad7f4de469cf5ba4f"
|
||||
integrity sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA==
|
||||
|
||||
"@types/http-proxy@^1.17.15":
|
||||
version "1.17.17"
|
||||
resolved "https://registry.yarnpkg.com/@types/http-proxy/-/http-proxy-1.17.17.tgz#d9e2c4571fe3507343cb210cd41790375e59a533"
|
||||
integrity sha512-ED6LB+Z1AVylNTu7hdzuBqOgMnvG/ld6wGCG8wFnAzKX5uyW2K3WD52v0gnLCTK/VLpXtKckgWuyScYK6cSPaw==
|
||||
dependencies:
|
||||
"@types/node" "*"
|
||||
|
||||
"@types/keygrip@*":
|
||||
version "1.0.6"
|
||||
resolved "https://registry.yarnpkg.com/@types/keygrip/-/keygrip-1.0.6.tgz#1749535181a2a9b02ac04a797550a8787345b740"
|
||||
@@ -2294,6 +2301,13 @@ debug@^4, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.2, debug@^4.3.3,
|
||||
dependencies:
|
||||
ms "^2.1.3"
|
||||
|
||||
debug@^4.3.6:
|
||||
version "4.4.3"
|
||||
resolved "https://registry.yarnpkg.com/debug/-/debug-4.4.3.tgz#c6ae432d9bd9662582fce08709b038c58e9e3d6a"
|
||||
integrity sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==
|
||||
dependencies:
|
||||
ms "^2.1.3"
|
||||
|
||||
debug@~4.3.1, debug@~4.3.2, debug@~4.3.4:
|
||||
version "4.3.5"
|
||||
resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.5.tgz#e83444eceb9fedd4a1da56d671ae2446a01a6e1e"
|
||||
@@ -2823,6 +2837,11 @@ eventemitter3@^3.0.0:
|
||||
resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-3.1.2.tgz#2d3d48f9c346698fce83a85d7d664e98535df6e7"
|
||||
integrity sha512-tvtQIeLVHjDkJYnzf2dgVMxfuSGJeM/7UCG17TT4EumTfNtF+0nebF/4zWOIkCreAbtNqhGEboB6BWrwqNaw4Q==
|
||||
|
||||
eventemitter3@^4.0.0:
|
||||
version "4.0.7"
|
||||
resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.7.tgz#2de9b68f6528d5644ef5c59526a1b4a07306169f"
|
||||
integrity sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==
|
||||
|
||||
exsolve@^1.0.1:
|
||||
version "1.0.4"
|
||||
resolved "https://registry.yarnpkg.com/exsolve/-/exsolve-1.0.4.tgz#7de5c75af82ecd15998328fbf5f2295883be3a39"
|
||||
@@ -2919,6 +2938,11 @@ flatted@^3.2.7, flatted@^3.2.9:
|
||||
resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.3.1.tgz#21db470729a6734d4997002f439cb308987f567a"
|
||||
integrity sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==
|
||||
|
||||
follow-redirects@^1.0.0:
|
||||
version "1.15.11"
|
||||
resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.11.tgz#777d73d72a92f8ec4d2e410eb47352a56b8e8340"
|
||||
integrity sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==
|
||||
|
||||
follow-redirects@^1.15.6:
|
||||
version "1.15.6"
|
||||
resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.6.tgz#7f815c0cda4249c74ff09e95ef97c23b5fd0399b"
|
||||
@@ -3296,6 +3320,27 @@ http-errors@~1.6.2:
|
||||
setprototypeof "1.1.0"
|
||||
statuses ">= 1.4.0 < 2"
|
||||
|
||||
http-proxy-middleware@^3.0.5:
|
||||
version "3.0.5"
|
||||
resolved "https://registry.yarnpkg.com/http-proxy-middleware/-/http-proxy-middleware-3.0.5.tgz#9dcde663edc44079bc5a9c63e03fe5e5d6037fab"
|
||||
integrity sha512-GLZZm1X38BPY4lkXA01jhwxvDoOkkXqjgVyUzVxiEK4iuRu03PZoYHhHRwxnfhQMDuaxi3vVri0YgSro/1oWqg==
|
||||
dependencies:
|
||||
"@types/http-proxy" "^1.17.15"
|
||||
debug "^4.3.6"
|
||||
http-proxy "^1.18.1"
|
||||
is-glob "^4.0.3"
|
||||
is-plain-object "^5.0.0"
|
||||
micromatch "^4.0.8"
|
||||
|
||||
http-proxy@^1.18.1:
|
||||
version "1.18.1"
|
||||
resolved "https://registry.yarnpkg.com/http-proxy/-/http-proxy-1.18.1.tgz#401541f0534884bbf95260334e72f88ee3976549"
|
||||
integrity sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==
|
||||
dependencies:
|
||||
eventemitter3 "^4.0.0"
|
||||
follow-redirects "^1.0.0"
|
||||
requires-port "^1.0.0"
|
||||
|
||||
http-signature@~1.4.0:
|
||||
version "1.4.0"
|
||||
resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.4.0.tgz#dee5a9ba2bf49416abc544abd6d967f6a94c8c3f"
|
||||
@@ -3519,6 +3564,11 @@ is-path-inside@^3.0.3:
|
||||
resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-3.0.3.tgz#d231362e53a07ff2b0e0ea7fed049161ffd16283"
|
||||
integrity sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==
|
||||
|
||||
is-plain-object@^5.0.0:
|
||||
version "5.0.0"
|
||||
resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-5.0.0.tgz#4427f50ab3429e9025ea7d52e9043a9ef4159344"
|
||||
integrity sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==
|
||||
|
||||
is-regex@^1.2.1:
|
||||
version "1.2.1"
|
||||
resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.2.1.tgz#76d70a3ed10ef9be48eb577887d74205bf0cad22"
|
||||
@@ -4084,7 +4134,7 @@ methods@^1.1.2:
|
||||
resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee"
|
||||
integrity sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==
|
||||
|
||||
micromatch@^4.0.5:
|
||||
micromatch@^4.0.5, micromatch@^4.0.8:
|
||||
version "4.0.8"
|
||||
resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.8.tgz#d66fa18f3a47076789320b9b1af32bd86d9fa202"
|
||||
integrity sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==
|
||||
|
||||
Reference in New Issue
Block a user