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

效果


相关推荐
Java陈序员6 分钟前
轻松设计 Logo!一款 Pornhub 风格的 Logo 在线生成器!
vue.js·node.js·vite
Gss7771 小时前
Linux 进程管理与计划任务详解
linux·运维·服务器
潜心专研的小张同学2 小时前
京东云轻量云服务器与腾讯云域名结合配置网站及申请SSL证书流程详解
运维·服务器·前端
one day3212 小时前
Linux和shell
linux·运维·服务器
gongzemin2 小时前
使用Node.js开发微信第三方平台后台
微信小程序·node.js·express
匀泪3 小时前
防火墙安全实验
服务器·网络·安全
仙云Q123 小时前
NAT技术与代理服务
linux·服务器·网络
没有余地 EliasJie4 小时前
Ubuntu/Debian 搭建 Nginx RTMP 服务器全攻略
服务器·ubuntu·debian
自由鬼4 小时前
AI赋能操作系统:通往智能运维的未来
linux·运维·服务器·人工智能·程序人生·ai·操作系统
鹏大师运维5 小时前
MBR与GPT分区表深度解析:硬盘分区该怎么选?
linux·运维·服务器·gpt·国产操作系统·mbr·统信uos