Guacamole远程桌面的使用和介绍(客户端)

2,467 阅读6分钟

什么是 Apache Guacamole?

Guacamole是一种HTML5 Web应用程序,可使用远程桌面协议(例如VNC或RDP)提供对桌面环境的访问。可使用HTTP或WebSocket通过基于JavaScript的隧道流式传输文本数据,以及一种客户端实现,该实现支持Guacamole协议,并与来自Windows的Guacamole协议流结合使用时可以呈现远程显示。提供了跨浏览器的鼠标和键盘事件,一个XML驱动的屏幕键盘以及具有硬件加速合成功能的同步嵌套层。

guacamole-common-js 是 Apache Guacamole 项目的一部分。Apache Guacamole 是一个无客户端的远程桌面网关,支持 VNC、RDP 和 SSH 协议。guacamole-common-js 是一个 JavaScript 库,提供了与 Guacamole 协议交互的客户端实现,通常用于在浏览器中实现远程桌面访问。

Guacamole 特点

  1. 无客户端:Guacamole允许从任何地方远程访问一个或多个桌面,而无需安装客户端,这意味着用户不需要在其设备上安装任何额外的软件,只需通过一个支持 HTML5 的浏览器即可访问远程桌面。
  2. 协议支持:Guacamole 支持多种协议,包括 VNC、RDP、SSH 等。
  3. 扩展性:通过插件和扩展,可以将 Guacamole 的功能扩展到支持特定的需求。
  4. 身份验证:支持多种身份验证机制,包括数据库、LDAP、OpenID 等。

Guacamole 的架构

组件划分:

  1. Guacamole Client:这是一个基于 HTML5 的客户端,可以在任何支持现代浏览器的设备上运行。用户通过浏览器访问 Guacamole Client,从而与远程桌面交互。

  2. Guacamole Server (guacd):这是 Guacamole 的核心代理组件。Guacd 处理与远程桌面的实际连接(如 RDP、VNC、SSH 等协议),并将这些连接转换为可以通过 WebSocket 协议传输的格式,以供 Guacamole Client 使用。

  3. Guacamole Protocol:Guacamole 使用自己的协议来在 Guacamole Client 和 guacd 之间传输数据。这种协议设计为可以在高延迟和低带宽条件下高效工作。

  4. Guacamole Web Application:这是一个用 Java 编写的应用程序,通常在一个支持 Java Servlet 的应用服务器(如 Tomcat)上运行。它负责用户身份验证、会话管理、连接配置等。

Guacamole是一个提供了基于HTML5 web应用程序的远程桌面代理服务器。通过使用Guacamole服务器,我们很轻松的在浏览器上远程访问Guacamole代理的主机,是一个无客户端远程桌面网关。支持标准协议,如VNC、RDP、SSH。称他为无客户端,是因为没有插件和客户端软件被要求。由于HTML5,一旦Guacamole 被安装到服务端,通过web 浏览器就可以访问你的桌面。

image.png

我们可以在浏览器访问Guacamole页面的时候,此时,浏览器会通过HTTP使用Guacamole协议与Guacamole 服务器中的Web服务器进行连接。Guacamole Web应用会从用户的请求中读取Guacamole协议,并将其转发给guacd(本地Guacamole代理)。Guacd根据web 应用转发过来的Guacamole协议来代替用户连接到远程桌面服务器。在Guacamole Web应用与guacd进行通信的时候,两者均不需要知道实际使用的远程桌面协议是什么,即协议不可知性。

Guacd guacd是Guacamole动态支持多种远程桌面协议(这里统称为客户端插件)和基于web连接远程桌面协议的核心. guacd是一个安装在Guacamole上后台运行的守护进程, 等待来自web的连接. guacd也不需要理解特定的远程桌面协议, 一旦客户端插件开始启动, 他和guacd独立运行, 并且拥有和web应用完全的同学权限.

Guacamole.Client常用方法

Guacamole.Client 是 Apache Guacamole 的 JavaScript 客户端库的一部分,它用于与 Guacamole 服务器进行通信和处理远程桌面的显示。在 Guacamole.Client 中,有许多方法可以用来管理连接、处理用户输入、绘制图像等。以下是一些常见的方法:

connect() - 连接到指定的 Guacamole 会话。
disconnect() - 断开当前的 Guacamole 会话。
sendSize() - 发送显示窗口的大小信息到服务器。
sendKeyEvent() - 发送键盘事件到服务器。
sendMouseState() - 发送鼠标状态到服务器。
getDisplay() - 获取显示对象,用于渲染远程内容。
getClipboard() - 获取剪贴板对象,用于处理剪贴板数据。
getAudio() - 获取音频对象,用于处理音频流。
getVideo() - 获取视频对象,用于处理视频流。
setChannelMask() - 设置要启用的通道掩码。
sendClipboard() - 发送剪贴板数据到服务器。
error() - 处理连接过程中出现的错误。
onstatechange() - 连接状态改变时的回调函数。
onclipboard() - 收到剪贴板数据时的回调函数。
onaudio() - 收到音频数据时的回调函数。
onvideo() - 收到视频数据时的回调函数。
onfile() - 收到文件传输时的回调函数。
onerror() - 发生错误时的回调函数。
getState() - 获取当前连接的状态。
setMimetype() - 设置数据通道的 MIME 类型。

使用步骤

  • 安装库:使用 npm 安装,npm install guacamole-common-js
  • 创建 WebSocket 连接:使用 WebSocketTunnel 类创建一个 WebSocket 连接到 Guacamole 服务器。
  • 创建 Guacamole 客户端: 使用 Guacamole.Client 类创建一个 Guacamole 客户端实例。
  • 处理用户输入:使用 Mouse 和 Keyboard 类处理用户的鼠标和键盘输入,通过 Guacamole.Mouse 和 Guacamole.Keyboard 来捕获和发送输入事件
  • 设置显示容器:使用 getDisplay() 方法获取显示元素,将其添加到 DOM 中以显示远程桌面。
  • 连接到远程桌面,guacClient.connect();
  • 断开连接时,guacClient.disconnect();

参考代码

import guacamole from 'guacamole-common-js';

// 创建 WebSocket 连接,创建传输管道
const webSocketClient = new guacamole.WebSocketTunnel(
    'ws://your-guacamole-server:8080/websocket-tunnel'
);

// WebSocket报错处理
webSocketClient.onerror = res => {};

// 状态改变
webSocketClient.onstatechange = state => {
    switch (state) {
        case 0:
            message.success('连接中.......');
            break;
        case 1:
            message.success('连接成功!');
            callback && callback();
            break;
        case 2:
            if (this.connectState === 0) {
                message.error('连接失败!');
            } else {
                message.warning('连接断开!');
            }
            break;
    }
};

// 创建 Guacamole 客户端
const guacClient = new guacamole.Client(webSocketClient);

/**
 * 接受监听,这是一个事件处理器,专门用于处理文件传输事件。当 Guacamole 服务器发送文件时,这个函数会被调用。
 * stream: 代表文件数据流的对象。它用于接收文件数据。
 * mimetype: 文件的 MIME 类型,描述文件的类型和格式。
 * */
guacClient.onfile = function (stream, mimetype, filename) {
    //通知服务端,已经收到了stream,向服务器发送一个确认
    stream.sendAck('OK', guacamole.Status.Code.SUCCESS);
    //开始处理输入流
    downloadFile(stream, mimetype, filename);
};

// 获取显示元素并添加到 DOM,获取显示画布
const display = guacClient.getDisplay().getElement();
document.getElementById('remote-desktop').appendChild(display);

// 连接到远程桌面
guacClient.connect();

// 处理鼠标输入
const mouse = new guacamole.Mouse(display);

mouse.onmousedown = mouse.onmouseup = mouse.onmousemove = mouseState => {
    guacClient.sendMouseState(mouseState);
};

// 处理鼠标和键盘事件
window.onresize = () => {
    client.sendSize(window.innerWidth, window.innerHeight);
};

// 处理键盘输入
const keyboard = new guacamole.Keyboard(document);

keyboard.onkeydown = keysym => {
    guacClient.sendKeyEvent(1, keysym);
};
keyboard.onkeyup = keysym => {
    guacClient.sendKeyEvent(0, keysym);
};

// 断开连接时清理
window.onunload = () => {
    guacClient.disconnect();
};

使用 guacamole-common-js 创建和管理远程桌面连接通常涉及到 Guacamole 服务器端的配置和设置。客户端代码需要通过 WebSocket 与 Guacamole 服务器通信,通常由后端生成连接令牌以验证并授权连接。

参考文章

juejin.cn/post/684490… (Guacamole实战)