node.js使用websockify代理VNC代理使用NoVNC进行远程桌面实现方案

UltraVNC作为VNC服务器

下载UltraVNC

UltraVNC官网下载地址

在每个需要被远程的PC上安装UltraVNC软件并且开启5900端口

配置UltraVNC

打开winvnc.exe

初次打开需要手动在exe文件根目录新建配置文件ultravnc.ini,这样setting后可以保存配置

下面是一些简单配置


其他不用动

代理实现使用NoVNC进行远程桌面

使用node.js使用websockify代理PC的RFB 5900端口让前端可以使用WebSocket通讯进行远程桌面,并且使用NoVNC进行远程桌面

原理

在Node.js服务端的服务器上安装websockify,然后客户端请求远程时执行websockify命令随机分配端口继续代理PC的5900端口,客户端就可以使用这随机分配的端口进行WebSocket远程桌面(传入ip和随机分配的端口给到NoVNC的页面中即可访问)

安装 websockify

  1. 首先需要下载Python
    Python下载地址windows

  2. 下载websockify

bash 复制代码
pip install websockify

独立版本的websockifyGitHub链接

下载后进入目录,运行:

bash 复制代码
npm install
npm link

然后你就可以用 websockify 命令了。

下载noVNC

noVNC github地址

需要将noVNC下载到vnc-proxy的public目录,到时候会用到vnc.html或者vnc_lite.html进行远程

核心代码

后端核心代码server.js

js 复制代码
// server.js
const express = require('express')
const path = require('path')
const { spawn } = require('child_process')

const app = express()
const HTTP_PORT = 3000
const WS_START_PORT = 6080

const proxies = {}      // key = targetIP:port
let nextPort = WS_START_PORT

// 映射noVnc静态资源到url
app.use('/', express.static(path.join(__dirname, 'public/novnc')))

// 启动新代理
app.get('/api/start-proxy', (req, res) => {
  const { ip, vncPort } = req.query
  if (!ip || !vncPort) return res.status(400).send('缺少参数 ip 或 vncPort')
  const target = `${ip}:${vncPort}`
  if (proxies[target]) return res.send(`代理已存在:ws://${req.hostname}:${proxies[target].wsPort} -> ${target}`)

  const wsPort = nextPort++
  // 使用websockify代理PC5900端口,后前端可以使用wsPort进行访问远程桌面
  const child = spawn('python', ['-m', 'websockify', '--web=./public/novnc', wsPort, target])
  child.on('exit', () => delete proxies[target])
  child.stdout.on('data', d => console.log(`[${target}] ${d}`))
  child.stderr.on('data', d => console.error(`[${target} ERROR] ${d}`))

  proxies[target] = { child, wsPort }
  res.send(`已启动:ws://${req.hostname}:${wsPort} -> ${target}`)
})

// 停止指定代理
app.get('/api/stop-proxy', (req, res) => {
  const { ip, vncPort } = req.query
  if (!ip || !vncPort) return res.status(400).send('缺少参数 ip 或 vncPort')
  const target = `${ip}:${vncPort}`
  const proxy = proxies[target]
  if (!proxy) return res.status(404).send('代理不存在')

  proxy.child.kill()
  delete proxies[target]
  res.send(`已停止代理:${target}`)
})

// 查看当前代理状态
app.get('/api/list-proxy', (req, res) => {
  const list = Object.entries(proxies).map(([target, { wsPort }]) => ({
    target,
    wsPort,
    url: `ws://${req.hostname}:${wsPort}`
  }))
  res.json(list)
})

app.listen(HTTP_PORT, () => {
  console.log(`服务运行:http://localhost:${HTTP_PORT}/vnc.html`)
})

项目使用命令

bash 复制代码
npm install express
node server.js

前端代码

doServer.vue组件

可以对后端进行请求实现:开启代理、停止代理、代理列表,然后通过代理列表点击进行远程桌面

js 复制代码
<template>
  <div>
    <h2>VNC 多端代理</h2>
    <div>
      <input v-model="ip" placeholder="VNC 设备 IP">
      <input v-model="vncPort" placeholder="VNC 端口" type="number">
      <button @click="startProxy">启动代理</button>
    </div>

    <h3>当前代理列表</h3>
    <button @click="refreshList">刷新</button>
    <ul>
      <li v-for="item in proxyList" :key="item.target">
        <span>{{ item.target }} → {{ item.url }}</span>
        <button @click="openVnc(item.wsPort)">打开</button>
        <button @click="stopProxy(item.target)">停止</button>
      </li>
    </ul>

    <p style="color:red">{{ message }}</p>
  </div>
</template>

<script>
import axios from 'axios'

export default {
  data() {
    return {
      ip: '127.0.0.1',
      vncPort: 5900,
      proxyList: [],
      message: '',
      ServerIp: '192.168.1.24',
      ServerPort: '3000'
    }
  },
  mounted() {
    this.refreshList()
  },
  methods: {
    async startProxy() {
      try {
        const res = await axios.get(`/api/start-proxy?ip=${this.ip}&vncPort=${this.vncPort}`)
        this.message = res.data
        this.refreshList()
      } catch (err) {
        this.message = '启动失败: ' + (err.response?.data || err.message)
      }
    },
    async stopProxy(target) {
      const [ip, vncPort] = target.split(':')
      try {
        const res = await axios.get(`/api/stop-proxy?ip=${ip}&vncPort=${vncPort}`)
        this.message = res.data
        this.refreshList()
      } catch (err) {
        this.message = '停止失败: ' + (err.response?.data || err.message)
      }
    },
    async refreshList() {
      try {
        const res = await axios.get('/api/list-proxy')
        this.proxyList = res.data
      } catch (err) {
        this.message = '获取代理失败: ' + (err.response?.data || err.message)
      }
    },
    openVnc(wsPort) {
      // scale=true自适应屏幕
      // host port ws的ip和端口  这些参数可以去vnc_lite或者vnc.html代码查看
      window.open(`http://${this.ServerIp}:${this.ServerPort}/vnc_lite.html?host=${this.ServerIp}&port=${wsPort}&scale=true`, '_blank')
    }
  }
}
</script>

启动项目

bash 复制代码
npm install
npm run serve

效果


相关推荐
Xの哲學29 分钟前
Linux 指针工作原理深入解析
linux·服务器·网络·架构·边缘计算
乌萨奇也要立志学C++32 分钟前
【Linux】进程信号(二)信号保存与捕捉全解析、可重入函数、volatile
linux·服务器
CryptoPP1 小时前
使用 KLineChart 这个轻量级的前端图表库
服务器·开发语言·前端·windows·后端·golang
Ai173163915791 小时前
2025.11.28国产AI计算卡参数信息汇总
服务器·图像处理·人工智能·神经网络·机器学习·视觉检测·transformer
一水鉴天1 小时前
整体设计 定稿 之1 devOps 中台的 结论性表述(豆包助手)
服务器·数据库·人工智能
HalvmånEver3 小时前
Linux:进程状态(进程二)
linux·运维·服务器
F***E2394 小时前
如何安装配置Goland并使用固定公网地址SSH远程连接本地服务器
运维·服务器·ssh
序属秋秋秋4 小时前
《Linux系统编程之进程环境》【环境变量】
linux·运维·服务器·c语言·c++·操作系统·系统编程
云边有个稻草人4 小时前
手机也能控 Linux?Cpolar+JuiceSSH 搞定内网远程
运维·服务器·cpolar
a***56064 小时前
node.js下载、安装、设置国内镜像源(永久)(Windows11)
node.js