cscg24-guacamole

CSCG 2024 Challenge 'Guacamole Mashup'
git clone https://git.sinitax.com/sinitax/cscg24-guacamole
Log | Files | Refs | sfeed.txt

advanced-configuration.md (34499B)


      1# Advanced Configuration for guacamole-lite
      2
      3## Table of Contents
      4
      5- [Introduction](#introduction)
      6- [WebSocket Options](#websocket-options)
      7    - [Configuration](#configuration)
      8- [Guacd Options](#guacd-options)
      9    - [Configuration](#configuration-1)
     10- [Client Options](#client-options)
     11    - [Encryption and Security](#encryption-and-security)
     12    - [Connection Settings](#connection-settings)
     13    - [Allowed Unencrypted Connection Settings in Query](#allowed-unencrypted-connection-settings-in-query)
     14    - [Connection Types](#connection-types)
     15    - [Logging](#logging)
     16- [Callbacks](#callbacks)
     17    - [`processConnectionSettings` Callback](#processconnectionsettings-callback)
     18- [Events](#events)
     19    - [`open` Event](#open-event)
     20    - [`close` Event](#close-event)
     21    - [`error` Event](#error-event)
     22- [Integration with Node.js Frameworks](#integration-with-nodejs-frameworks)
     23    - [Considerations for Integration](#considerations-for-integration)
     24    - [Example of Integrating with Express.js](#example-of-integrating-with-expressjs)
     25- [Additional Examples and Resources](#additional-examples-and-resources)
     26    - [Contents of the Examples Directory](#contents-of-the-examples-directory)
     27
     28## Introduction
     29
     30`guacamole-lite` is a lightweight Node.js server that implements the server-side portion of the Apache Guacamole
     31protocol. Apache Guacamole is an open-source clientless remote desktop gateway that supports standard protocols like
     32VNC, RDP, and SSH. Unlike the standard Guacamole server, which is Java-based, `guacamole-lite` is designed to be easily
     33integrated into Node.js applications, offering a more streamlined and flexible approach to remote desktop connectivity.
     34
     35The primary goal of `guacamole-lite` is to provide developers with a simple yet powerful way to embed remote desktop
     36functionality into their web applications. It is particularly well-suited for projects that already have user and
     37connection management systems in place and do not require the full suite of features provided by the traditional
     38Guacamole server.
     39
     40This documentation focuses on the advanced configuration options available in `guacamole-lite`. It is intended for
     41developers who wish to customize and extend the functionality of their `guacamole-lite` deployment beyond the basic
     42setup. The advanced configuration covers a range of topics, including WebSocket options, `guacd`
     43connection settings, client options for encryption and security, logging, and handling of connection parameters.
     44
     45---
     46
     47## WebSocket Options
     48
     49The `websocketOptions` object in `guacamole-lite` configures the WebSocket server, which is essential for maintaining a
     50persistent, full-duplex communication channel required for remote desktop interactions. The WebSocket server handles
     51incoming connections from clients and facilitates communication between the web client and the `guacd`.
     52
     53### Configuration
     54
     55The WebSocket server can be customized through various properties within the `websocketOptions` object. Here's an
     56example configuration:
     57
     58```javascript
     59const websocketOptions = {
     60    port: 8080, // The port on which the WebSocket server will listen for connections.
     61    host: '0.0.0.0', // The host address to bind to. Use '0.0.0.0' to accept connections on all IPv4 addresses.
     62};
     63```
     64
     65The `websocketOptions` object is passed directly to the `ws` WebSocket library, allowing any supported options by `ws`
     66to be included. For a comprehensive list of all the options you can configure, refer to
     67the [ws documentation](https://github.com/websockets/ws/blob/master/doc/ws.md#new-websocketserveroptions-callback).
     68
     69In the context of `guacamole-lite`, the WebSocket server is typically configured to listen on a specific port and IP
     70address. This setup ensures that the server is reachable by clients and can handle the necessary communication for
     71remote desktop sessions.
     72
     73---
     74
     75## Guacd Options
     76
     77The `guacdOptions` configuration in `guacamole-lite` specifies how it should connect to the `guacd`, which is
     78responsible for handling the remote desktop protocols and translating them into the Guacamole
     79protocol.
     80
     81### Configuration
     82
     83The connection to `guacd` can be customized through the `guacdOptions` object. However, specifying this object is
     84optional. If not provided, `guacamole-lite` will use the default values. Here's an example of setting `guacdOptions`:
     85
     86```javascript
     87const guacdOptions = {
     88    host: 'localhost', // Optional. Default is '127.0.0.1'.
     89    port: 4822,       // Optional. Default is 4822.
     90};
     91```
     92
     93If `guacdOptions` is omitted, `guacamole-lite` will attempt to connect to `guacd` on the local machine (`127.0.0.1`) on
     94port `4822`. These defaults are suitable for most scenarios where `guacamole-lite` and `guacd` are running on the same
     95server.
     96
     97`guacdOptions` object is directly passed to net.createConnection() function, allowing any supported options by
     98net.createConnection() to be included. For a comprehensive list of all the options you can configure, refer to
     99the [net documentation](https://nodejs.org/api/net.html#netcreateconnectionpath-connectlistener).
    100
    101---
    102
    103## Client Options
    104
    105The `clientOptions` object is where you define the behavior and capabilities of your `guacamole-lite` instance. It
    106allows you to set up encryption for secure communication, establish default settings for various connection types,
    107configure logging levels, and specify which connection settings can be overridden by query parameters.
    108
    109Here's a high-level view of the `clientOptions` structure:
    110
    111```javascript
    112const clientOptions = {
    113    // Encryption settings for secure token handling
    114    crypt: {
    115        cypher: 'AES-256-CBC',
    116        key: 'MySuperSecretKeyForParamsToken12',
    117    },
    118    // Default settings for remote desktop connections
    119    connectionDefaultSettings: {
    120        rdp: {
    121            'hostname': 'localhost',
    122            'port': '3389',
    123            // More RDP-specific settings...
    124        },
    125        // Default settings for other protocols (VNC, SSH, etc.)...
    126    },
    127    // Logging configuration
    128    log: {
    129        level: 'VERBOSE', // Other levels: 'QUIET', 'ERRORS', 'NORMAL', 'DEBUG'
    130        // Custom log functions (if needed)...
    131    },
    132    // Allowed unencrypted connection settings in query parameters
    133    allowedUnencryptedConnectionSettings: {
    134        rdp: ['width', 'height', 'dpi'],
    135        // Allowed settings for other protocols...
    136    },
    137    // Other client-specific options...
    138};
    139```
    140
    141---
    142
    143### Encryption and Security
    144
    145Unlike the full `guacamole-client`, `guacamole-lite` does not maintain its own database for managing users, remote
    146hosts, and credentials. Instead, it relies on the integrating application to supply these parameters. Since the
    147transmission of these parameters often occurs through potentially insecure channels, such as the client's browser, it is
    148crucial to ensure their security and integrity. To address these concerns, `guacamole-lite` employs encrypted tokens to
    149pass connection details.
    150
    151An encrypted token is a secure method of transmitting information where the data is first converted into a ciphertext
    152using an encryption algorithm and a secret key. This process ensures two critical aspects:
    153
    154a) **Authentication**: The encrypted token verifies that the connection parameters were indeed generated by the
    155application and have not been forged or tampered with by any third party.
    156
    157b) **Confidentiality**: Sensitive information, such as login credentials to the remote host, remains concealed from the
    158client. Only `guacamole-lite` and the application that generated the token can decrypt and access the contained
    159information.
    160
    161The encrypted token is a Base64-encoded string that encapsulates the encrypted connection parameters, including an
    162initialization vector (IV) and the encrypted data (value). The IV is a random value used to ensure that the encryption
    163process produces different ciphertexts even if the same data and key are used multiple times. The value is the actual
    164encrypted JSON object containing the connection settings.
    165
    166#### Encryption Key Requirements for `AES-256-CBC`
    167
    168For `AES-256-CBC`, the encryption key must be 32 bytes (256 bits) in length. This key, combined with the IV, is used to
    169encrypt the connection parameters securely. It is essential to use a cryptographically strong key, which should be
    170generated using a secure random number generator and kept confidential.
    171
    172#### Security Implications
    173
    174Allowing unencrypted connection settings to be transmitted can lead to the exposure of sensitive data. To mitigate this
    175risk, `guacamole-lite` uses encrypted tokens to securely pass connection details. However, certain non-sensitive
    176parameters, such as screen resolution or color depth, can be passed unencrypted via query parameters if explicitly
    177permitted in the `allowedUnencryptedConnectionSettings`.
    178
    179#### Best Practices
    180
    181Best practices for generating and managing encrypted connection tokens include:
    182
    183- Generating the encrypted token on the backend server to avoid exposing the secret key and remote host credentials to
    184  the client.
    185    - If a malicious actor gains access to the key and the encryption algorithm, they can start encrypting their own
    186      tokens and connecting to any remote host, essentially **turning your `guacamole-lite` server into an open relay**
    187      for their malicious activities. So it's very advisable to generate the token on the backend server to avoid
    188      exposing the key and remote host credentials to the client.
    189    - Additionally, if you consider generating the token on the frontend, you will need to expose the remote host
    190      address, login and password to the client, which then can be used to connect to the remote host directly,
    191      bypassing your `guacamole-lite` server.
    192- Generating a robust, random encryption key and safeguarding it and securely storing it:
    193    - Never store the key in your source code or version control system (git).
    194    - Never hardcode the key in your application.
    195    - Never send it to your frontend client or use the frontend client to encrypt the token.
    196- Using a unique IV for each encryption operation to prevent recognizable patterns in the ciphertext.
    197- Restricting the token's validity period to minimize the risk of replay attacks.
    198
    199#### `crypt` Settings in `clientOptions`
    200
    201The `crypt` settings within `clientOptions` should be set as follows:
    202
    203```javascript
    204const clientOptions = {
    205    crypt: {
    206        cypher: 'AES-256-CBC',
    207        key: 'MySuperSecretKeyForParamsToken12', // Replace with your 32-byte key
    208    },
    209    // Other client options...
    210};
    211```
    212
    213#### Encrypting the Token
    214
    215To encrypt a token object containing connection settings, follow these steps:
    216
    2171. Generate an initialization vector (IV) for encryption. The IV should be random and 16 bytes long for `AES-256-CBC`.
    2182. Take the JSON object with connection settings and encrypt it using the cipher and key from `clientOptions`.
    2193. Base64 encode the result of the encryption (this will be the `value`).
    2204. Create another JSON object containing the base64-encoded IV and the encrypted `value`.
    2215. Base64 encode the entire JSON object from step 4 to produce the final token.
    222
    223#### Example Code in Different Languages
    224
    225For practical examples of how to encrypt the token in different programming languages, refer to the following links:
    226
    227- [Node.js Example](../examples/encrypt_token.js)
    228- [PHP Example](../examples/encrypt_token.php)
    229- [Python Example](../examples/encrypt_token.py)
    230
    231These examples illustrate the encryption process step-by-step, ensuring that you can securely generate tokens for use
    232with `guacamole-lite`.
    233
    234---
    235
    236### Connection Settings
    237
    238In `guacamole-lite`, connection settings are crucial for establishing a remote desktop session. These settings include
    239parameters such as hostname, port, and protocol-specific options like screen resolution or authentication credentials.
    240To manage these settings flexibly, `guacamole-lite` merges them from three sources: default settings, encrypted tokens,
    241and query parameters.
    242
    243#### Merging Connection Settings
    244
    245The `connectionDefaultSettings` within `clientOptions` serve as a baseline for all connections. These defaults can be
    246overridden by the settings provided in the encrypted token, which in turn can be overridden by the settings specified in
    247the query parameters. This merging process ensures that the most specific settings take precedence.
    248
    249Here's how the merging process works:
    250
    2511. Start with the `connectionDefaultSettings` as the base.
    2522. Apply settings from the encrypted token, overriding any defaults.
    2533. Apply settings from the query parameters, overriding both the defaults and token settings.
    254
    255The precedence order of settings is as follows: query parameters > encrypted token > `connectionDefaultSettings`.
    256
    257#### Example Configuration
    258
    259Here's an example of how you might set default connection options for RDP within `clientOptions`:
    260
    261```javascript
    262const clientOptions = {
    263    // Other client options...
    264    connectionDefaultSettings: {
    265        rdp: {
    266            'hostname': 'remote.example.com',
    267            'port': '3389',
    268            'security': 'nla',
    269            'ignore-cert': true,
    270            'enable-wallpaper': false,
    271            // Additional RDP-specific default settings...
    272        },
    273        // Default settings for other protocols (VNC, SSH, etc.)...
    274    },
    275    // Other client options...
    276};
    277```
    278
    279In this example, we've specified a set of default RDP connection settings that will be used unless overridden by the
    280encrypted token or query parameters. For instance, if the encrypted token contains a different hostname or if the query
    281includes a different port, those values will be used instead of the defaults.
    282
    283By carefully configuring the `connectionDefaultSettings`, you can ensure that `guacamole-lite` has sensible defaults for
    284each protocol while still allowing for flexibility based on the needs of individual connections.
    285
    286---
    287
    288### Allowed Unencrypted Connection Settings in Query
    289
    290For certain use cases, it may be necessary to allow clients to override specific connection settings via unencrypted
    291query parameters. This can be useful for dynamically adjusting settings like screen resolution or color depth without
    292the need to generate a new encrypted token. `guacamole-lite` provides a mechanism to specify which connection settings
    293can be safely passed in the query string without encryption.
    294
    295#### Usage of `allowedUnencryptedConnectionSettings`
    296
    297The `allowedUnencryptedConnectionSettings` within `clientOptions` is an object that defines which connection settings
    298can be overridden by query parameters for each connection type. This feature is designed to be used with caution, as it
    299can potentially expose your guacamole-lite server to abuse by malicious actors. As best practice, don't allow any
    300sensitive parameters like hostname, port, or credentials to be overridden in the query string.
    301
    302#### Default Parameters
    303
    304By default, `guacamole-lite` allows only a limited set of non-sensitive parameters to be overridden via the query
    305string: `width`, `height`, `dpi`, `audio`, `video`, `image` and `timezone`. These parameters are safe to pass
    306unencrypted and can be used to adjust the screen resolution, audio and video codecs, image formats, and time zone of the
    307remote desktop session.
    308
    309#### Whitelisting Parameters
    310
    311To create your own whitelist of parameters, add them to the `allowedUnencryptedConnectionSettings` object under the
    312appropriate connection type. They will override the default parameters.
    313Here's an example of how to allow additional VNC settings:
    314
    315```javascript
    316const clientOptions = {
    317    // Other client options...
    318    allowedUnencryptedConnectionSettings: {
    319        vnc: [
    320            'width',
    321            'height',
    322            'dpi',
    323            'color-depth', // Additional allowed parameter
    324        ],
    325        // Settings for other protocols...
    326    },
    327};
    328```
    329
    330In this configuration, `color-depth` has been added to the list of allowed unencrypted settings for VNC connections.
    331Even though `width`, `height`, and `dpi` are allowed by default, they must be explicitly included in your whitelist if
    332you wish to allow them to be overridden in the query string, otherwise they will be ignored.
    333
    334#### Sending Multiple Values in Query
    335
    336To send multiple values for the same parameter, such as different audio codecs, the client can include the parameter
    337multiple times in the query string. Here's an example of how a client might specify multiple audio codecs for an RDP
    338connection:
    339
    340```
    341ws://your-guacamole-server:8080/?token=encryptedToken&audio=audio%2FL8&audio=audio%2FL16
    342```
    343
    344In this example, the `audio` parameter is provided twice, indicating that both `audio/L8` and `audio/L16` codecs are
    345supported by the client. `guacamole-lite` will parse the query string and use the provided values to override the
    346default or token-provided settings.
    347
    348---
    349
    350### Connection Types
    351
    352`guacamole-lite` supports several connection types, each designed to facilitate access to different kinds of remote
    353systems. The primary connection types are RDP, VNC, SSH, and Telnet, which cover a broad range of use cases:
    354
    355- **RDP (Remote Desktop Protocol)**: Primarily used for accessing Windows desktops and servers, RDP provides a rich
    356  graphical interface for users. It is ideal for remote work, IT support, and administration tasks on Windows systems.
    357- **VNC (Virtual Network Computing)**: A versatile protocol that allows for remote control of a computer's desktop
    358  environment, VNC is used across various operating systems, including Linux, macOS, and Windows. It is suitable for
    359  system administration and accessing graphical applications remotely.
    360- **SSH (Secure Shell)**: A protocol used for secure command-line access to Unix-like operating systems, SSH is
    361  essential for server management, secure file transfers, and running text-based applications in a secure manner.
    362- **Telnet**: An older protocol used for two-way interactive communication, Telnet is less secure than SSH and is
    363  generally used in controlled environments for managing network devices or systems that do not support SSH.
    364
    365Each connection type has its own set of parameters and client handshake instructions, which are used to establish and
    366configure the remote desktop session. `guacamole-lite` allows for default settings to be specified for each protocol,
    367which can be combined with settings from the encrypted connection token provided by the client.
    368
    369#### Connection Parameters and Client Handshake Instructions
    370
    371Each connection type has specific parameters required for establishing a session.
    372These parameters include details such as hostname, port, and protocol-specific settings like color depth or audio
    373support.
    374Additionally, they can contain client handshake instructions which used to negotiate the capabilities between the
    375client and the server, such as supported audio and video codecs or image formats.
    376
    377#### Example Configuration
    378
    379Below is an example configuration that outlines the default settings for each supported connection type
    380in `guacamole-lite`. These settings include both connection parameters and client handshake instructions:
    381
    382```javascript
    383const clientOptions = {
    384    // Default settings for different connection types
    385    connectionDefaultSettings: {
    386        rdp: {
    387            'create-drive-path': true,
    388            'security': 'any',
    389            'ignore-cert': true,
    390            'enable-wallpaper': false,
    391            'create-recording-path': true,
    392            'audio': ['audio/L16'],
    393            'video': null,
    394            'image': ['image/png', 'image/jpeg'],
    395            'timezone': 'America/New_York',
    396        },
    397        vnc: {
    398            'swap-red-blue': true,
    399            'disable-paste': false,
    400        },
    401        ssh: {
    402            'enable-sftp': true,
    403            'green-black': true,
    404        },
    405        telnet: {
    406            'login-success-regex': '.*',
    407        },
    408    },
    409    // Other client options...
    410};
    411```
    412
    413These defaults provide a starting point for each protocol and can be overridden by the encrypted token or query
    414parameters. For instance, the RDP defaults set up a drive path for file transfer, specify a security setting, and
    415configure audio and image settings for the session. Similarly, VNC, SSH, and Telnet have their own relevant defaults.
    416
    417For a detailed list of connection parameters for each protocol, refer to
    418the [Guacamole documentation on configuring connections](https://guacamole.incubator.apache.org/doc/gug/configuring-guacamole.html#configuring-connections).
    419Additionally,
    420the [protocol reference for client handshake instructions](https://guacamole.incubator.apache.org/doc/gug/protocol-reference.html#client-handshake-instructions)
    421provides guidance on the handshake instructions common to all protocols.
    422
    423Both connection parameters and client handshake instructions can be mixed in the same object.
    424
    425For a more comprehensive example and comments on configuring `connectionDefaultSettings`, please see
    426the [advanced_configuration.js example](../examples/advanced_configuration.js) included with `guacamole-lite`.
    427
    428
    429---
    430
    431### Logging
    432
    433Effective logging is essential for monitoring the behavior of `guacamole-lite` and diagnosing issues. The logging system
    434in `guacamole-lite` provides various levels of verbosity, allowing developers to choose the amount of detail they
    435receive in the logs.
    436
    437#### Log Levels
    438
    439`guacamole-lite` supports the following log levels, which determine the verbosity of the output:
    440
    441- **QUIET**: No logs will be output.
    442- **ERRORS**: Only error messages will be logged.
    443- **NORMAL**: Errors and essential operational messages will be logged, such as startup and shutdown notices.
    444- **VERBOSE**: In addition to errors and operational messages, connection-related messages will be logged, including
    445  when connections are opened or closed.
    446- **DEBUG**: The most verbose level, including all the above plus detailed debugging information, such as inter-server
    447  communication between `guacamole-lite` and `guacd` with all opcodes sent and received.
    448
    449#### Example Configuration of Log Level
    450
    451To configure the log level, set the `level` property within the `log` object in `clientOptions`. Here's an example:
    452
    453```javascript
    454const clientOptions = {
    455    // Other client options...
    456    log: {
    457        level: 'VERBOSE', // Adjust the log level as needed.
    458    },
    459};
    460```
    461
    462In this configuration, `VERBOSE` logging is enabled, which provides a detailed account of the operational status
    463without the extensive debugging information that the `DEBUG` level would include.
    464
    465#### Custom Log Functions
    466
    467`guacamole-lite` allows for the implementation of custom log functions, providing flexibility to redirect log output as
    468needed, such as to a file or a logging service.
    469
    470Here's a simple example of custom log functions that write logs to a file:
    471
    472```javascript
    473const fs = require('fs');
    474const logFile = fs.createWriteStream('guacamole-lite.log', {flags: 'a'});
    475
    476const clientOptions = {
    477    // Other client options...
    478    log: {
    479        level: 'VERBOSE',
    480        stdLog: (...args) => {
    481            logFile.write(new Date().toISOString() + ' - ' + args.join(' ') + '\n');
    482        },
    483        errorLog: (...args) => {
    484            logFile.write(new Date().toISOString() + ' - ERROR - ' + args.join(' ') + '\n');
    485        },
    486    },
    487};
    488```
    489
    490In this example, the `stdLog` function writes standard log messages to a file, while `errorLog` writes error messages.
    491Both functions prepend a timestamp and differentiate error messages by including the word "ERROR".
    492
    493---
    494
    495## Callbacks
    496
    497Callbacks in `guacamole-lite` provide hooks that allow developers to intercept and manipulate the connection process.
    498For now the only available callback is `processConnectionSettings`, which offers a way to validate and modify connection
    499parameters dynamically. We may add more callbacks in the future to support additional use cases.
    500
    501### `processConnectionSettings` Callback
    502
    503The `processConnectionSettings` callback is invoked after a WebSocket connection with the client has been established
    504and the connection token has been decrypted, but before a connection to `guacd` is opened. This callback is an
    505opportunity to adjust connection settings on the fly or to validate them before proceeding with the connection.
    506
    507The callback function receives two arguments:
    508
    5091. `settings`: An object containing the decrypted connection settings.
    5102. `callback`: A function that must be called with two parameters: an error (if any) and the modified settings.
    511
    512If the `callback` is called with an error, the connection attempt will be rejected. Otherwise, the modified settings
    513will be used to establish the connection with `guacd`.
    514
    515### Custom Parameters in Encrypted Token
    516
    517Developers can include custom parameters within the encrypted token to pass additional data required for the connection.
    518These custom parameters can then be accessed and utilized within the `processConnectionSettings` callback.
    519
    520For example, a custom `expiration` parameter can be used to verify the token's validity and prevent replay attacks. If
    521the current time is greater than the expiration timestamp, the token is considered expired, and the connection is
    522rejected:
    523
    524```javascript
    525if (settings['expiration'] < Date.now()) {
    526    console.error('Token expired');
    527    return callback(new Error('Token expired'));
    528}
    529```
    530
    531### Validating and Modifying Connection Parameters
    532
    533The `processConnectionSettings` callback can also be used to modify connection settings based on the provided
    534parameters. For instance, if a `userId` is included in the token, it can be used to assign a unique drive path for file
    535transfer for each user:
    536
    537```javascript
    538settings.connection['drive-path'] = '/tmp/guacamole_' + settings['userId'];
    539```
    540
    541This approach allows for personalized settings for each user or connection, enhancing the flexibility and security
    542of `guacamole-lite`.
    543
    544### Example Configuration
    545
    546Here is an example of how to define the `callbacks` object with the `processConnectionSettings` callback:
    547
    548```javascript
    549const callbacks = {
    550    processConnectionSettings: (settings, callback) => {
    551        // Validate the token's expiration date
    552        if (settings['expiration'] < Date.now()) {
    553            console.error('Token expired');
    554            return callback(new Error('Token expired'));
    555        }
    556
    557        // Modify the connection settings based on the userId
    558        settings.connection['drive-path'] = '/tmp/guacamole_' + settings['userId'];
    559
    560        // Proceed with the modified settings
    561        callback(null, settings);
    562    }
    563};
    564```
    565
    566In this configuration, the callback checks for token expiration and sets a user-specific drive path. The modified
    567settings are then forwarded to `guacd` to establish the connection.
    568
    569---
    570
    571## Events
    572
    573`guacamole-lite` emits several events that provide hooks into the lifecycle of a client's connection. These events allow
    574developers to execute custom logic at various stages, such as when a connection is established, terminated, or
    575encounters an error. The primary events emitted by `guacamole-lite` are `open`, `close`, and `error`.
    576
    577### `open` Event
    578
    579The `open` event is emitted when a connection to the remote desktop host (via `guacd`) is successfully established. This
    580event signifies that the initial handshake has been completed and the client is ready to start sending and receiving
    581data.
    582
    583### `close` Event
    584
    585The `close` event is triggered when a connection is closed. This can happen for various reasons, such as the client
    586disconnecting, an error occurring, or the server shutting down. The event provides an opportunity to perform cleanup
    587tasks or log the disconnection.
    588
    589### `error` Event
    590
    591The `error` event is emitted when an error occurs during the connection process. This could be due to issues with the
    592WebSocket connection, problems during the handshake with `guacd`, or any other exceptions that arise. Handling this
    593event
    594is crucial for robust error logging and debugging.
    595
    596### Use Cases for Events
    597
    598#### Notifying a Backend System
    599
    600One common use case for the `open` and `close` events is to notify a backend system about the user's connection status.
    601This can be particularly useful for session management, such as performing cleanup tasks on the remote machine after a
    602user logs out or transferring session recordings for storage.
    603
    604When the `open` event is triggered, indicating that a new session has started, a notification can be sent to the backend
    605server:
    606
    607```javascript
    608guacServer.on('open', (clientConnection) => {
    609    const url = `http://our-backend-server/api/connection/open?userId=${clientConnection.connectionSettings['userId']}`;
    610    http.request(url).end();
    611});
    612```
    613
    614Similarly, when the `close` event is emitted, it can signal the end of a session. This is an opportune moment to perform
    615any necessary cleanup or handle session recordings:
    616
    617```javascript
    618guacServer.on('close', (clientConnection, error) => {
    619    const url = `http://our-backend-server/api/connection/close?userId=${clientConnection.connectionSettings['userId']}&error=${encodeURIComponent(error.message)}`;
    620    http.request(url).end();
    621    // Additional logic for handling session recordings, if applicable...
    622});
    623```
    624
    625The `error` event can be used to log errors or notify the backend system of any issues that occurred during the session:
    626
    627```javascript
    628guacServer.on('error', (clientConnection, error) => {
    629    console.error(`Error on connection ID: ${clientConnection.connectionId}`, error);
    630    // Additional error handling logic...
    631});
    632```
    633
    634Each event provides the `ClientConnection` object as a parameter, which contains the connection settings, including the
    635user ID. This object can be used to access detailed information about the connection for logging or other purposes.
    636The `close` and `error` events also receive an error object that contains the reason for the disconnection, which can be
    637useful for debugging and auditing.
    638
    639By leveraging these events, developers can ensure that their systems remain informed about the state of remote desktop
    640sessions and can react accordingly to maintain a seamless user experience.
    641
    642---
    643
    644## Integration with Node.js Frameworks
    645
    646Integrating `guacamole-lite` with other Node.js frameworks can enhance its capabilities and allow it to fit seamlessly
    647into a broader application ecosystem. When integrating `guacamole-lite`, it's important to consider how it will interact
    648with the existing framework's routing, middleware, and server setup.
    649
    650### Considerations for Integration
    651
    652- **Routing**: Determine how `guacamole-lite` will fit into your application's routing structure. You may need to set up
    653  specific routes to handle WebSocket connections or to serve the client-side assets required for `guacamole-lite`.
    654- **Middleware**: If your application uses middleware for tasks like authentication, logging, or CORS handling, ensure
    655  that these are compatible with `guacamole-lite` and do not interfere with its operation.
    656- **Server Configuration**: `guacamole-lite` needs to be attached to an HTTP or HTTPS server instance. Ensure that the
    657  server configuration aligns with `guacamole-lite`'s requirements and that there are no conflicts with other server
    658  instances within the framework.
    659
    660### Example of Integrating with Express.js
    661
    662Express.js is a popular web application framework for Node.js known for its simplicity and flexibility. Below is an
    663example of how to integrate `guacamole-lite` with an Express.js application:
    664
    665```javascript
    666#!/usr/bin/env node
    667
    668const GuacamoleLite = require('guacamole-lite');
    669const express = require('express');
    670const http = require('http');
    671
    672// Create an Express application
    673const app = express();
    674
    675// Create an HTTP server and attach the Express application to it
    676const server = http.createServer(app);
    677
    678// Define `guacd` connection options
    679const guacdOptions = {
    680    port: 4822 // The port on which `guacd` is listening
    681};
    682
    683// Define client options, including encryption settings
    684const clientOptions = {
    685    crypt: {
    686        cypher: 'AES-256-CBC',
    687        key: 'MySuperSecretKeyForParamsToken12'
    688    }
    689};
    690
    691// Create a new instance of GuacamoleLite and attach it to the HTTP server
    692const guacServer = new GuacamoleLite(
    693    {server}, // Pass the server instance to GuacamoleLite
    694    guacdOptions,
    695    clientOptions
    696);
    697
    698// Start listening for connections on port 8080
    699server.listen(8080, () => {
    700    console.log('Express and guacamole-lite server running on port 8080');
    701});
    702```
    703
    704In this example, `guacamole-lite` is integrated into the Express.js application by creating an HTTP server instance and
    705passing it to the `GuacamoleLite` constructor. This setup allows `guacamole-lite` to handle WebSocket connections while
    706the Express application can continue to serve other routes and middleware as usual.
    707
    708By following this pattern, you can integrate `guacamole-lite` into your Node.js application built with Express.js or a
    709similar framework, allowing you to leverage the full capabilities of both `guacamole-lite` and the framework.
    710
    711---
    712
    713## Additional Examples and Resources
    714
    715For developers looking to dive deeper into the practical implementation of `guacamole-lite`, the project's `examples`
    716directory provides a wealth of resources. These examples cover a range of scenarios, from basic server setup to advanced
    717configuration, and include scripts for encrypting tokens in various programming languages.
    718
    719### Contents of the Examples Directory
    720
    721The `examples` directory within the `guacamole-lite` project contains the following files:
    722
    723- `advanced_configuration.js`: Demonstrates how to set up `guacamole-lite` with advanced options, including custom
    724  connection settings and callbacks.
    725- `basic_server.js`: Provides a simple example of how to get a `guacamole-lite` server up and running with minimal
    726  configuration.
    727- `encrypt_token.js`: Shows how to encrypt a connection token using Node.js, ensuring secure transmission of connection
    728  parameters.
    729- `encrypt_token.php`: A PHP script for encrypting the connection token, useful for applications with a PHP backend.
    730- `encrypt_token.py`: A Python example for token encryption, catering to systems where Python is the server-side
    731  language of choice.
    732- `expressjs.js`: Illustrates how to integrate `guacamole-lite` with an Express.js application, combining web server
    733  functionality with remote desktop capabilities.
    734
    735These examples are designed to be informative and easily adaptable to your specific use case. Whether you're just
    736getting started with `guacamole-lite` or looking to implement more complex features, the examples directory is a
    737valuable resource.