cscg24-guacamole

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

advanced_configuration.js (9088B)


      1#!/usr/bin/env node
      2
      3const GuacamoleLite = require('guacamole-lite');
      4const http = require("http");
      5
      6// [OPTIONAL] websocketOptions
      7// this is passed directly to 'ws' library when creating a websocket server.
      8// like this: new WebSocket.Server(websocketOptions)
      9// See https://github.com/websockets/ws/blob/master/doc/ws.md#new-websocketserveroptions-callback
     10const websocketOptions = {
     11    port: 8080 // We will accept connections to this port. Default: 8080
     12};
     13
     14// [OPTIONAL] guacdOptions
     15// this is passed directly to net.connect() function when connecting to guacd.
     16// See https://nodejs.org/api/net.html#net_net_connect_port_host_connectlistener
     17const guacdOptions = {
     18    host: 'localhost', // Hostname or IP address of guacd server, Default: '127.0.0.1'
     19    port: 4822 // Port of guacd server. Default: 4822
     20};
     21
     22// [REQUIRED] clientOptions
     23const clientOptions = {
     24
     25    // [REQUIRED] crypt
     26    // Encryption settings used to decrypt the connection token.
     27    // Ideally, you'd want to keep them in a separate file and not commit them to your repository.
     28    crypt: {
     29        cypher: 'AES-256-CBC',
     30        key: 'MySuperSecretKeyForParamsToken12'
     31    },
     32
     33    // [OPTIONAL] log
     34    // Logger settings.
     35    log: {
     36        // You can set the log level to one of the following values:
     37        // 'QUIET' - no logs
     38        // 'ERRORS' - only errors
     39        // 'NORMAL' - errors + minimal logs (startup and shutdown messages)
     40        // 'VERBOSE' - (default) normal + connection messages (opened, closed, guacd exchange, etc)
     41        // 'DEBUG' - verbose + all OPCODES sent/received within guacamole sessions
     42        level: 'DEBUG',
     43
     44        // By default, GuacamoleLite will log to stdout and stderr.
     45        // You can override the default logging functions by providing your own stdLog and/or errorLog functions.
     46        stdLog: (...args) => {
     47            console.log('[MyLog]', ...args)
     48        },
     49        errorLog: (...args) => {
     50            console.error('[MyLog]', ...args)
     51        }
     52    },
     53
     54    // [OPTIONAL] connectionDefaultSettings
     55    // Default settings for different connection types.
     56    // These are added to the connection settings received from the client in the encrypted connection token.
     57    // Note that this it a mix of connection parameters and client handshake instructions.
     58    // There is no common set of parameters for all connection types (RDP, VNC, etc.), each type must be configured
     59    // separately.
     60    // For the list of connection parameters
     61    // see https://guacamole.incubator.apache.org/doc/gug/configuring-guacamole.html#configuring-connections
     62    // For the list of client handshake instructions
     63    // see https://guacamole.incubator.apache.org/doc/gug/protocol-reference.html#client-handshake-instructions
     64    connectionDefaultSettings: {
     65        rdp: {
     66            // RDP connection parameters
     67            // https://guacamole.incubator.apache.org/doc/gug/configuring-guacamole.html#rdp
     68            // https://guacamole.incubator.apache.org/doc/gug/configuring-guacamole.html#common-configuration-options
     69            'create-drive-path': true,
     70            'security': 'any',
     71            'ignore-cert': true,
     72            'enable-wallpaper': false,
     73            'create-recording-path': true,
     74
     75            // Client handshake instructions
     76            // https://guacamole.incubator.apache.org/doc/gug/protocol-reference.html#client-handshake-instructions
     77            'audio': ['audio/L16'],
     78            'video': null,
     79            'image': ['image/png', 'image/jpeg'],
     80            'timezone': 'America/New_York',
     81        },
     82        vnc: {
     83            // VNC connection parameters
     84            // https://guacamole.incubator.apache.org/doc/gug/configuring-guacamole.html#vnc
     85            // https://guacamole.incubator.apache.org/doc/gug/configuring-guacamole.html#common-configuration-options
     86            'swap-red-blue': true,
     87            'disable-paste': false,
     88        },
     89        ssh: {
     90            // SSH connection parameters
     91            // https://guacamole.incubator.apache.org/doc/gug/configuring-guacamole.html#ssh
     92            // https://guacamole.incubator.apache.org/doc/gug/configuring-guacamole.html#common-configuration-options
     93            'enable-sftp': true,
     94            'green-black': true,
     95        },
     96        telnet: {
     97            // Telnet connection parameters
     98            // https://guacamole.incubator.apache.org/doc/gug/configuring-guacamole.html#telnet
     99            // https://guacamole.incubator.apache.org/doc/gug/configuring-guacamole.html#common-configuration-options
    100            'login-success-regex': '.*',
    101        },
    102        kubernetes: {
    103            // Kubernetes connection parameters
    104            // https://guacamole.incubator.apache.org/doc/gug/configuring-guacamole.html#kubernetes
    105            // https://guacamole.incubator.apache.org/doc/gug/configuring-guacamole.html#common-configuration-options
    106            'exec-command': 'bash',
    107        }
    108    },
    109
    110    // [OPTIONAL] allowedUnencryptedConnectionSettings
    111    // The connection parameters from the encrypted token can be overridden by the client by sending them
    112    // unencrypted in the query string.
    113    // For example: ws://guacamole-lite:8080/?token=<encrypted>&width=800&height=600&dpi=120
    114
    115    // This is useful when you want to generate a connection token on your backend server (which is a good idea,
    116    // because you don't want to expose connection parameters like username, password, etc to the client), but
    117    // allow your frontend to override some of the connection parameters like screen width, height, etc.
    118
    119    // Because we don't want the client to be able to override all parameters, including the sensitive ones,
    120    // we need to specify the list parameters that can be sent unencrypted for each connection type.
    121
    122    // By default, only the following unencrypted parameters are allowed:
    123    // width, height, dpi, audio, video, image, timezone
    124    allowedUnencryptedConnectionSettings: {
    125        rdp: [
    126            'width',
    127            'height',
    128            'dpi',
    129            'create-drive-path' // we added this parameter to the list of allowed unencrypted parameters
    130        ]
    131    },
    132};
    133
    134// [OPTIONAL]
    135// Callbacks for different events.
    136const callbacks = {
    137    processConnectionSettings: (settings, callback) => {
    138        // processConnectionSettings:
    139        // This is called after establishing a websocket connection with the client, decrypting the connection token,
    140        // and before opening a connection to guacd.
    141        // Can be used to modify the connection settings "on the fly" based on the user id, connection id, etc.
    142        // Or to validate the connection settings and reject the connection.
    143        // It receives the connection settings and a callback function as parameters.
    144        // The callback function must be called with two parameters: error and modified settings.
    145        // In the end, you MUST call the callback function with either an error or the modified settings.
    146        // If the callback is called with an error, the connection will be rejected.
    147
    148        // You can encrypt ANY custom parameters in the connection token and use them here.
    149        // In this example, we are using the "expiration" parameter to validate the token's expiration date.
    150        // This is a good practice to prevent token replay attacks.
    151        if (settings['expiration'] < Date.now()) {
    152            console.error('Token expired');
    153
    154            // Reject the connection
    155            return callback(new Error('Token expired'));
    156        }
    157
    158        // You can also send "userId" in the connection token and use it dynamically modify the connection settings.
    159        // In this example, we are using the "userId" parameter to set individual drive paths for each user.
    160        settings.connection['drive-path'] = '/tmp/guacamole_' + settings['userId'];
    161
    162        // Forward the modified settings to guacd
    163        callback(null, settings);
    164    }
    165};
    166
    167// Create a new instance of GuacamoleLite
    168const guacServer = new GuacamoleLite(
    169    websocketOptions,
    170    guacdOptions,
    171    clientOptions,
    172    callbacks
    173);
    174
    175
    176// In the following example, we are using the "open" and "close" events to notify our backend server
    177// about the user's connection status.
    178// Each event receives the ClientConnection object as a parameter, which contains the connection settings, including
    179// the user id, etc. See ClientConnection.js for more details, 'close' and 'error' events also receive an error object,
    180// containing the disconnect reason.
    181guacServer.on('open', (clientConnection) => {
    182    const url = 'http://our-backend-server/api/connection/open'
    183        + '?userId=' + clientConnection.connectionSettings['userId'];
    184
    185    http.request(url).end();
    186});
    187
    188guacServer.on('close', (clientConnection, error) => {
    189    const url = 'http://our-backend-server/api/connection/close'
    190        + '?userId=' + clientConnection.connectionSettings['userId']
    191        + '&error=' + encodeURIComponent(error.message);
    192
    193    http.request(url).end();
    194});
    195
    196guacServer.on('error', (clientConnection, error) => {
    197    console.error(clientConnection, error);
    198});