Apache Guacamole

Apache Guacamole

I’ve been making use of Apache Guacamole which allows web browser hosted sessions for SSH, VNC, RDP, Telnet and more, for a while now and wanted to document some thoughts and a setup instruction.

With a web based administration linked to a database, multi factor authentication, logging (and even session video recording), to name but a few of the features of this software – I’ve really come to love the simplicity of Guacamole, and the price as it’s free!

In my mind two use cases became quickly apparent:

1) Network Management/Administration – a central server with SSH access to switches/servers and RDP access to Windows servers. This would enable logging of admin actions, two factor access on devices with don’t support MFA natively, lockdown of SSH/RDP access to a controlled source (the Guacamole server) and removal of the need to distribute credentials for devices, as Guacamole allows these to be stored against a connection and hidden from the user using the connection

2) Guest access to apps/resources – by configuring a DMZ Guacamole server with unique credentials for guest (external contractors, clients, etc.) to connect to a Microsoft Remote App Session Host, or linux equivalent X11 server, guests can access internal resources in a controlled fashion whilst “air-gapping” the data containing systems from the outside world. For added security Guacamole can be reverse proxied to an external connection (via nginx or IIS ARR for example).

Below is a basic configuration for installing Guacamole 1.2.0 on an Amazon Web Services hosted instance of Ubuntu 20.04, note that the Instance must have direct Internet access during the setup process.

Once the steps are completed you will have an operational Guacamole server (which can be used for either of the scenarios listed above), using the database back end to store users and configuration items, with TOTP 2-factor authentication.

It is assumed you already have a basic understanding of Linux based operating systems, and have configured AWS (if being used) correctly for your VPC, Security Groups, Internet/NAT Gateway, etc.

It's also assumed that when reading and following these instructions you will customise them for your configuration (i.e. usernames, database names, passwords, etc.) - Whilst these instructions get you to an operational state they are not a Production ready system without changing the default passwords and hardening the operating system and OWASP test considerations for the front end application.

Initial Installation

sudo apt-get update
sudo apt-get upgrade
sudo apt install -y gcc g++ libcairo2-dev libjpeg-turbo8-dev libpng-dev libtool-bin libossp-uuid-dev libavcodec-dev libavutil-dev libswscale-dev freerdp2-dev libpango1.0-dev libssh2-1-dev libvncserver-dev libtelnet-dev libssl-dev libvorbis-dev libwebp-dev
wget https://downloads.apache.org/guacamole/1.2.0/source/guacamole-server-1.2.0.tar.gz
tar xzf guacamole-server-1.2.0.tar.gz
cd guacamole-server-1.2.0
sudo ./configure --with-init-dir=/etc/init.d
sudo apt install make
make
sudo make install
sudo ldconfig
sudo systemctl enable guacd
sudo /etc/init.d/guacd start
sudo apt install tomcat9 tomcat9-admin tomcat9-common tomcat9-user -y
sudo ufw allow 8080/tcp
sudo mkdir /etc/guacamole
sudo wget https://downloads.apache.org/guacamole/1.2.0/binary/guacamole-1.2.0.war -o /etc/guacamole/guacamole.war
sudo ln -s /etc/guacamole/guacamole.war /var/lib/tomcat9/webapps/
sudo systemctl restart tomcat9 guacd
sudo mkdir /etc/guacamole/{extensions,lib}
sudo nano /etc/default/tomcat9
  GUACAMOLE_HOME=/etc/guacamole
sudo nano /etc/guacamole/guacamole.properties
  guacd-hostname: localhost
  guacd-port:     4822
  user-mapping:   /etc/guacamole/user-mapping.xml
  auth-provider:  net.sourceforge.guacamole.net.basic.BasicFileAuthenticationProvider
sudo ln -s /etc/guacamole /usr/share/tomcat9/.guacamole
echo -n password | openssl md5
     (copy the hash output) - e.g. 5f4dcc3b5aa765d61d8327deb882cf99
sudo nano /etc/guacamole/user-mapping.xml
  <user-mapping>
    <authorize
      username="guacadmin"
      password="5f4dcc3b5aa765d61d8327deb882cf99"
      encoding="md5">
    </authorize>
  </user-mapping>
sudo systemctl restart tomcat9 guacd

At this point login to the web interface to make sure everything is working:
http://<IPADDRESS>:8080/guacamole
username = “guacadmin”
password=”password”


Adding Database Authentication and Management

sudo apt install mariadb-server mariadb-client
sudo mysql_secure_installation
     set password: Y
     remove anon users: Y
     disallow root login remotely: Y
     remove test database: Y
     reload privilege tables now: Y
sudo mysql -p
     enter password from above
CREATE DATABASE guacamole_db;
CREATE USER 'guacamole_user'@'localhost' IDENTIFIED BY 'passw0rd';
GRANT SELECT,INSERT,UPDATE,DELETE ON guacamole_db.* TO 'guacamole_user'@'localhost';
FLUSH PRIVILEGES;
This section is only required for AWS hosted Ubuntu servers
CREATE USER ubuntu@localhost IDENTIFIED BY 'password';
GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, RELOAD, PROCESS, REFERENCES, INDEX, ALTER, SHOW DATABASES, CREATE TEMPORARY TABLES, LOCK TABLES, EXECUTE, REPLICATION SLAVE, REPLICATION CLIENT, CREATE VIEW, SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE, CREATE USER, EVENT, TRIGGER ON *.* TO ubuntu@localhost WITH GRANT OPTION;

quit;
sudo wget https://downloads.apache.org/guacamole/1.2.0/binary/guacamole-auth-jdbc-1.2.0.tar.gz
tar vfx guacamole-auth-jdbc-1.2.0.tar.gz
sudo cat guacamole-auth-jdbc-1.2.0/mysql/schema/*.sql | mysql -p guacamole_db
sudo cp guacamole-auth-jdbc-1.2.0/mysql/guacamole-auth-jdbc-mysql-1.2.0.jar /etc/guacamole/extensions/
sudo wget https://dev.mysql.com/get/Downloads/Connector-J/mysql-connector-java-8.0.21.tar.gz
tar xvzf mysql-connector-java-8.0.21.tar.gz
sudo cp mysql-connector-java-8.0.21/mysql-connector-java-8.0.21.jar /etc/guacamole/lib/
sudo nano /etc/guacamole/guacamole.properties
  mysql-hostname:                            localhost
  mysql-port:                                3306
  mysql-database:                            guacamole_db
  mysql-username:                            guacamole_user
  mysql-password:                            passw0rd
  mysql-user-password-min-length:            8
  mysql-user-password-require-multiple-case: true
  mysql-user-password-require-symbol:        true
  mysql-user-password-require-digit:         true
  mysql-user-password-prohibit-username:     true
  mysql-user-password-min-age:               1
  mysql-user-password-max-age:               45
  mysql-user-password-history-size:          24
  mysql-user-required:                       true
sudo systemctl restart tomcat9

Now check the web interface again, this time you’ll be logging in with the default credentials from the database, connect to http://<IPADDRESS>:8080/guacamole
username = “guacadmin”
password=”guacadmin”


Adding TOTP 2-Factor Authentication

sudo wget https://downloads.apache.org/guacamole/1.2.0/binary/guacamole-auth-totp-1.2.0.tar.gz
tar vfx guacamole-auth-totp-1.2.0.tar.gz
sudo cp guacamole-auth-totp-1.2.0/guacamole-auth-totp-1.2.0.jar /etc/guacamole/extensions/
sudo nano /etc/guacamole/guacamole.properties
  totp-issuer:    My Guacamole
  totp-digits:    6
  totp-period:    30
  totp-mode:      sha1
sudo systemctl restart tomcat9

Now login again, this time you’ll be asked to enroll for TOTP using a smartphone application of your choice (Google Authenticator for example)

Important! Google Authenticator does not like the default guacadmin account – create a new admin account first, enroll TOTP for that account and check you can access all system settings, then disable the default guacadmin account


Notes

To clear a users TOTP you’ll need to manually edit the database, at time of writing there is no function within the GUI to do this, but there is an open change request to add this feature. The below example would clear the TOTP from the ‘guacadmin’ account:

mysql -p
use guacamole_db;
SELECT user_id FROM guacamole_user INNER JOIN guacamole_entity ON guacamole_entity.entity_id = guacamole_user.entity_id WHERE guacamole_entity.name = 'guacadmin';
UPDATE guacamole_user_attribute SET attribute_value='false' WHERE attribute_name = 'guac-totp-key-confirmed' and user_id = '1';
quit;

When connecting to a server or computer using RDP and wanting to allow the user to enter credentials at the logon screen (i.e. not pre-provide credentials within guacamole connection settings), you’ll need to make the following Registry changes on the server/computer you are connecting to:

[HKLM\SYSTEM\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp]
Change “SecurityLayer” value to 1
Verify “UserAuthentication” value is 0
Note the above tells the server/computer to use the RDP encryption protocol - this is insecure, ensure you have other protections in place (limiting TCP port 3389 from only the guacamole server for example) to keep the connection safe.