Guacamole

From Leo's Notes
Last edited on 24 January 2023, at 23:46.

Apache Guacamole is a web-accessible remote desktop gateway that supports RDP, VNC, and text-based connections via SSH and telnet.

Quick introduction

The Guacamole server contains two parts: The web application itself running on Tomcat, and the guacamole proxy service (guacd) that connects to the remote desktop endpoints. Under the hood, the RDP/VNC/SSH connection data from guacd is sent to the Guacamole server using the Guacamole protocol which is then relayed back to the user and rendered using Guacamole's HTML5 based client. As a result, the client is unaware of the underlying protocol (which actually poses several limitations which will be covered later).

Limitations

Guacamole's documentation doesn't list limitations clearly and these are the limitations that I've encountered after playing with it for a short period.

  • Guacamole must connect to a VNC enabled desktop either anonymously or with pre-defined credentials. You cannot have Guacamole 'login' for a user using their Guacamole credentials.
  • RDP works like VNC but with NLA support for RDP (I haven't tested this) which would allow the user to enter their RDP credentials when connecting. There is no way to make Guacamole pass credentials to RDP however, so you can't make Guacamole work like a VDI using a pool of desktops.
  • In VNC, sessions cannot be 'resized' on the fly. Guacamole's protocol doesn't seem to support it.
  • In VNC, copy/paste clipboard data cannot be copied out of a remote desktop; it can only be copied in. This works if I use x11vnc as the VNC server rather than the Gnome built-in screen sharing feature.
  • VNC based connections are extremely slow. Using x11vnc is slightly better than vino, but there's easily 1-2 second delays on my local instance all hosted on the same hypervisor and accessed via a local gigabit LAN connection.
  • VNC connection settings hard code authentication credentials. You cannot 'login' as a user on the remote desktop

Setup

You can either install Guacamole directly on a server or use the prebuilt Docker containers. Review the documentation at:

Setup Guacamole using Docker Compose

The easiest way to set up Guacamole is with the following docker-compose.yml stack. I am using Traefik as the reverse proxy which handles SSL termination and strips the /guacamole from the URI path, but is completely optional. If you don't use Traefik, simply remove the Traefik network and labels and serve port 8080.

First, create the following docker-compose.yml file.

version: '3.3'

services:
  guacd:
    image: guacamole/guacd
    restart: unless-stopped
    volumes:
      - /volumes/guacamole/guacd/drive:/drive:rw
      - /volumes/guacamole/guacd/record:/record:rw
    networks:
      - internal

  guacamole:
    image: guacamole/guacamole
    restart: unless-stopped
    depends_on:
      - guacd
      - db
    environment:
      GUACD_HOSTNAME: guacd
      MYSQL_HOSTNAME: db
      MYSQL_DATABASE: guacamole
      MYSQL_USER: guacamole
      MYSQL_PASSWORD: 41e930486c6de5ebda96  <-- change me
    expose:
      - "8080"
    labels:
      - traefik.enable=true
      - traefik.docker.network=traefik
      - traefik.http.middlewares.guacamole-prefix.addprefix.prefix=/guacamole
      - traefik.http.middlewares.guacamole-https-redirect.redirectscheme.scheme=https
      # http
      - traefik.http.routers.guacamole.entrypoints=http
      - traefik.http.routers.guacamole.rule=Host(`guacamole.steamr.com`)
      - traefik.http.routers.guacamole.service=guacamole-https
      - traefik.http.routers.guacamole.middlewares=guacamole-https-redirect
      # https
      - traefik.http.routers.guacamole-https.entrypoints=https
      - traefik.http.routers.guacamole-https.rule=Host(`guacamole.steamr.com`)
      - traefik.http.routers.guacamole-https.tls=true
      - traefik.http.routers.guacamole-https.service=guacamole-https
      - traefik.http.services.guacamole-https.loadbalancer.server.port=8080
      - traefik.http.routers.guacamole-https.middlewares=guacamole-prefix
    networks:
      - internal
      - traefik

  db:
    image: mariadb:latest
    environment:
      MYSQL_ROOT_PASSWORD: 41e930486c6de5ebda96  <-- change me
      MYSQL_USER: guacamole
      MYSQL_PASSWORD: 41e930486c6de5ebda96  <-- change me
      MYSQL_DATABASE: guacamole
    restart: unless-stopped
    volumes:
      # To obtain this file, run: docker run --rm guacamole/guacamole /opt/guacamole/bin/initdb.sh --mysql > initdb.sql
      - /volumes/guacamole/initdb.sql:/initdb.sql
      - /volumes/guacamole/db:/var/lib/mysql/:rw
    networks:
      - internal

networks:
  internal:
  traefik:
    name: traefik
    external: true

Next, bring the container stack up:

# docker-compose pull
# docker run --rm guacamole/guacamole /opt/guacamole/bin/initdb.sh --mysql > /volumes/guacamole/initdb.sql
# docker-compose up -d

Set up the database:

## Figure out which container is your database and then load the initial database
# docker ps | grep guacamole
# docker exec -ti $DB_CONTAINER_ID bash
root@db # mysql -u root -p$MYSQL_ROOT_PASSWORD $MYSQL_DATABASE < /initdb.sql
Guacamole Login
Guacamole Login

You should be able to reach the Guacamole server and see a login page. If not, restart the Guacamole container and try again. If you see an error message, you likely misconfigured the database connection or didn't populate the Guacamole database properly.

Login using the following credentials:

  • Username: guacadmin
  • Password: guacadmin

When setting up a new connection, enter 'guacd' as the Guacamole proxy hostname, 4822 as the port, and 'none' for encryption.

Setting up a VNC connection

Log in as an administrator and navigate to 'Settings', then 'Connections'. Click on 'New Connection'. Specify the following:

  1. guacd: If using the Docker compose stack above, the hostname would just be 'guacd' on port 4822 without encryption
  2. parameters: The hostname to your VNC server. Port is typically 5900. I leave all other fields blank. I use X11vnc as my VNC server which starts up with my login.
  3. Audio: The 'Audio server name' should point to a PulseAudio service. To make this work, you will have to tweak PulseAudio to allow remote connections via TCP. Edit /etc/pulse/default.pa and uncomment out the line 'load-module module-native-protocol-tcp'. Add the following arguments to the module such that the final linke looks like this: load-module module-native-protocol-tcp auth-ip-acl=10.1.2.11/32 auth-anonymous=1. Restart PulseAudio (killall pulseaudio should work and it should be restarted automatically or just reboot). Verify it's working by running ss -lntp | grep 4713.

Using Guacamole

Review the documentation at https://guacamole.apache.org/doc/gug/using-guacamole.html.

Alt + Ctrl + Shift is used to bring up or hide the Guacamole menu sidebar.

Tasks

Changing the default /guacamole URI path

The default URI path for Guacamole is /guacamole (Eg. http://server:8080/guacamole). You may wish to change it so that Guacamole is served on the root path (/).

The official Docker image

If using the Guacamole Docker image, restart the container with an environment variable WEBAPP_CONTEXT=ROOT.

Direct install on a server

If using Guacamole on a server directly, you will need to rename the guacamole Tomcat war file:

  1. Navigate to /var/lib/tomcat8/webapps/ and delete the guacamole directory.
  2. Rename the guacamole.war file to ROOT.war.
  3. Restart Tomcat

Traefik reverse proxy

If you're using Traefik as the reverse proxy, you can create a middleware that adds the /guacamole prefix transparently. Use the following configs with Traefik v2.

traefik.http.middlewares.guacamole-prefix.addprefix.prefix=/guacamole
traefik.http.routers.guacamole.middlewares=guacamole-prefix

Troubleshooting

Incorrect VNC sessions screen size

I encountered an issue with x11vnc where the screen size is about 10-15 times taller than it should be. The contents of the extraneous areas appear to be bits and pieces of other windows and overlays. The cause of this was that x11vnc was started with the ncache option which is used to expand the framebuffer for caching windows and window contents. This however requires a VNC client that supports this option which Guacamole's proxy (guacd) doesn't seem to support.

To fix this issue, re-run x11vnc with the -noncache option.