Apache Gucamole es una herramienta que sirve como puerta de enlace sin complementos ni software de cliente para protocolos estándar como VNC, RDP y SSH. Y todo esto desde el navegador web gracias a HTML5. Hay multitud de páginas que indican como instalar Apache Guacamole, aunque una de las formas más interesantes es mediante Docker Compose. El problema es que prácticamente la documentación de cómo conseguir desplegar Apache Guacamole con Docker Compose y que se autentique contra LDAP o el Active Directory es casi nula, constándonos varios días a mi compañero y a mí hasta hacerlo funcionar.
Tabla de contenido
Instalación básica Apache Guacamole con Docker Compose
Para poder realizar el despliegue, tenemos que tener en cuenta las siguientes premisas:
- Tener instalado Docker
- Tener corriendo Docker compose
- Git
- Hacerlo desde un sistema Linux* y tener openssl.
*En el caso de hacerlo con Windows, hay que tener openssl instalado y realizar algunas pequeñas modificaciones en el fichero prerare.sh que comentaré más adelante.
Gracias a boschkundendienst tenemos su proyecto guacamole-docker-compose que explica como con 4 comandos podemos desplegar nuestro primer Apache Guacamole.
Estos comandos son:
git clone "https://github.com/boschkundendienst/guacamole-docker-compose.git"
cd guacamole-docker-compose
./prepare.sh
docker-compose up -d
Y ya tendríamos Apache Guacamole disponible en https://tuIP:8443/. El usuario por defecto es guacadmin y la contraseña por defecto es guacadmin.
docker-compose.yml
Aunque en la página de github del proyecto de BoschKindendienst explica el fichero Docker-componse.yml, y la estructura, os lo detallo:
Redes
La siguiente parte de docker-compose.yml creará una red con nombre guacnetwork_composeen en modo puente(bridged)
...
# networks
# create a network 'guacnetwork_compose' in mode 'bridged'
networks:
guacnetwork_compose:
driver: bridge
...
Servicios
Guacd
La siguiente parte de docker-compose.yml creará el servicio guacd. guacd es el corazón de Guacamole que carga dinámicamente soporte para protocolos de escritorio remoto llamados “complementos de cliente» (client plugins) y los conecta a escritorios remotos según las instrucciones recibidas de la aplicación web. El contenedor se llamará guacd_compose basado en la imagen de Docker guacamole/guacd conectada a nuestra red creada previamente guacnetwork_compose. Además, mapeamos las 2 carpetas locales ./drive y ./record en el contenedor. Podemos usarlos más tarde para mapear unidades de usuario y almacenar datos de sesiones.
...
services:
# guacd
guacd:
container_name: guacd_compose
image: guacamole/guacd
networks:
guacnetwork_compose:
restart: always
volumes:
- ./drive:/drive:rw
- ./record:/record:rw
...
PostgreSQL
La siguiente parte de docker-compose.yml creará una instancia de PostgreSQL usando la imagen oficial de docker. Esta imagen es configurable usando variables de entorno. Por ejemplo, inicializará una base de datos si se encuentra un script de inicialización en la carpeta /docker-entrypoint-initdb.d dentro de la imagen. Dado que asignamos la carpeta local ./init dentro del contenedor, docker-entrypoint-initdb.d podemos inicializar la base de datos para guacamole usando nuestro propio script ( ./init/initdb.sql).
...
postgres:
container_name: postgres_guacamole_compose
environment:
PGDATA: /var/lib/postgresql/data/guacamole
POSTGRES_DB: guacamole_db
POSTGRES_PASSWORD: ChooseYourOwnPasswordHere1234
POSTGRES_USER: guacamole_user
image: postgres
networks:
guacnetwork_compose:
restart: always
volumes:
- ./init:/docker-entrypoint-initdb.d:ro
- ./data:/var/lib/postgresql/data:rw
...
Guacamole
La siguiente parte de docker-compose.yml creará una instancia de guacamole mediante el uso de la imagen Docker guacamole desde docker hub. Esta imagen también es configurable y aquí es donde más adelante explicaremos como configurar la autenticación contra un LDAP o Active Directory mediante variables de entorno. En este fichero, está configurado para conectarse a la instancia de postgres creada previamente utilizando un nombre de usuario y contraseña y la base de datos guacamole_db. El puerto 8080 solo está expuesto localmente. En el siguiente punto se explica la instancia nginx para su acceso público.
...
guacamole:
container_name: guacamole_compose
depends_on:
- guacd
- postgres
environment:
GUACD_HOSTNAME: guacd
POSTGRES_DATABASE: guacamole_db
POSTGRES_HOSTNAME: postgres
POSTGRES_PASSWORD: ChooseYourOwnPasswordHere1234
POSTGRES_USER: guacamole_user
image: guacamole/guacamole
links:
- guacd
networks:
guacnetwork_compose:
ports:
- 8080/tcp
restart: always
...
nginx
La última parte de docker-compose.yml creará una instancia de nginx que asigna el puerto público 8443 al puerto interno 443. Luego, el puerto interno 443 se asigna a guacamole utilizando los archivos ./nginx.conf y ./nginx/mysite.template. El contenedor utilizará el certificado autofirmado generado con prepare.sh previamente en ./nginx/ssl/ con ./nginx/ssl/self-ssl.key y ./nginx/ssl/self.cert.
...
nginx:
container_name: nginx_guacamole_compose
restart: always
image: nginx
volumes:
- ./nginx/ssl/self.cert:/etc/nginx/ssl/self.cert:ro
- ./nginx/ssl/self-ssl.key:/etc/nginx/ssl/self-ssl.key:ro
- ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro
- ./nginx/mysite.template:/etc/nginx/conf.d/default.conf:ro
ports:
- 8443:443
links:
- guacamole
networks:
guacnetwork_compose:
# run nginx
command: /bin/bash -c "nginx -g 'daemon off;'"
...
prepare.sh
prepare.sh es un pequeño script para crear ./init/initdb.sql descargando la imagen docker guacamole/guacamole. Lo inicia así:
docker run --rm guacamole/guacamole /opt/guacamole/bin/initdb.sh --postgres > ./init/initdb.sql
Esto crea el archivo de inicialización de base de datos necesario para postgres.
prepare.sh también crea el certificado autofirmado ./nginx/ssl/self.cert y la clave privada ./nginx/ssl/self-ssl.key que utiliza nginx para https.
Si ejecutamos Docker compose desde Windows, este fichero hay que adaptarlo, ya que está pensado con instrucciones de Linux.
reset.sh
Si deseamos restablecer todo de nuevo, únicamente ejecutaremos ./reset.sh.
Autenticación con LDAP o Active Directoy
Aquí el kit de la cuestión de este post y que tantos días nos llevó hasta conseguir hacerlo funcionar. Seguramente porque aún somos un poco novatos en el mundo del Docker y Docker-compose.
Lo primero (aunque fue de lo último que encontramos, porque todas nuestras búsquedas se basaban en docker-compose) es que en la página siguiente de documentación oficial de Apache Guacamole nos indica como pasar las variable para la autenticación de LDAP, o en nuestro caso para Active Directory. Estas variables son:
Variable | Descripción |
LDAP_HOSTNAME | El nombre de host o la dirección IP de su servidor LDAP. |
LDAP_USER_BASE_DN | La base del DN para todos los usuarios de Guacamole. Todos los usuarios de Guacamole que se autenticarán contra LDAP deben ser descendientes de este DN base. |
LDAP_PORT | El puerto en el que escucha su servidor LDAP. De forma predeterminada, será 389 para LDAP sin cifrar o LDAP con STARTTLS y 636 para LDAP sobre SSL (LDAPS). |
LDAP_ENCRYPTION_METHOD | El mecanismo de encriptación que debe usar Guacamole al comunicarse con su servidor LDAP. Los valores legales son «ninguno» para LDAP sin cifrar, «ssl» para LDAP sobre SSL/TLS (comúnmente conocido como LDAPS) o «starttls» para STARTTLS. Si se omite, no se utilizará el cifrado. |
LDAP_GROUP_BASE_DN | La base del DN para todos los grupos a los que se puede hacer referencia dentro de las configuraciones de Guacamole usando el atributo estándar seeAlso . Todos los grupos que se usarán para controlar el acceso a las configuraciones de Guacamole deben ser descendientes de este DN base. Si se omite esta variable, el atributo seeAlso no tendrá efecto en las configuraciones de Guacamole. |
LDAP_SEARCH_BIND_DN | El DN (Nombre Distinguido) del usuario para vincular al autenticar a los usuarios que intentan iniciar sesión. Si se especifica, Guacamole consultará el directorio LDAP para determinar el DN de cada usuario que inicia sesión. Si se omite, el DN de cada usuario será derivado directamente usando el DN base especificado con LDAP_USER_BASE_DN. |
LDAP_SEARCH_BIND_PASSWORD | La contraseña para proporcionar al servidor LDAP cuando se vincula LDAP_SEARCH_BIND_DNpara autenticar a otros usuarios. Esta variable solo se utiliza si LDAP_SEARCH_BIND_DNse especifica. Si se omite, pero LDAP_SEARCH_BIND_DNse especifica, Guacamole intentará vincularse con el servidor LDAP sin contraseña. |
LDAP_USERNAME_ATTRIBUTE | El atributo o atributos que contienen el nombre de usuario dentro de todos los objetos de usuario de Guacamole en el directorio LDAP. Habitualmente, y por defecto, será simplemente » uid «. Si su directorio LDAP contiene usuarios cuyos nombres de usuario están dictados por diferentes atributos, se pueden especificar múltiples atributos aquí, separados por comas, pero tenga cuidado: hacerlo requiere que se proporcione un DN de búsqueda con LDAP_SEARCH_BIND_DN . |
LDAP_CONFIG_BASE_DN | La base del DN para todas las configuraciones de Guacamole. Si se omite, las configuraciones de las conexiones de Guacamole simplemente no se consultarán desde el directorio LDAP y deberá almacenarlas en otro lugar, como dentro de una base de datos MySQL o PostgreSQL. |
Sabiendo el significado de estas variables, ya podemos configurar nuestro docker-compose.yml en el apartado de Guacamole de este modo:
...
guacamole:
container_name: guacamole_compose
depends_on:
- guacd
- postgres
environment:
GUACD_HOSTNAME: guacd
POSTGRES_DATABASE: guacamole_db
POSTGRES_HOSTNAME: postgres
POSTGRES_PASSWORD: ChooseYourOwnPasswordHere1234
POSTGRES_USER: guacamole_user
LDAP_HOSTNAME: DIRECCIÓN_IP_CONTROLADOR_DE_DOMINIO
LDAP_PORT: 389 # O seguro: 636
LDAP_USER_BASE_DN: OU=ruta,DC=dominio,DC=local
LDAP_USERNAME_ATTRIBUTE: samAccountName
LDAP_CONFIG_BASE_DN: OU=ruta,DC=dominio,DC=local
LDAP_ENCRYPTION_METHOD: none # O seguro: ssl, starttls
LDAP_SEARCH_BIND_DN: cn=usuario_LDAP,OU=ruta,DC=dominio,DC=local
LDAP_SEARCH_BIND_PASSWORD:CONTRASEÑA
image: guacamole/guacamole
links:
- guacd
networks:
guacnetwork_compose:
ports:
- 8080/tcp
restart: always
...
Para estar seguro que esto funciona, podemos acceder a la máquina guacamole_compose y ejecutar el siguiente comando para ver si se ha añadido la configuración de LDAP al fichero guacamole.properties:
$ cat /home/guacamole/.guacamole/guacamole.properties
Y podremos ver el contenido del fichero guacamole.properties
# guacamole.properties - generated Sat Dec 3 04:12:02 PM UTC 2022
guacd-hostname: guacd
guacd-port: 4822
postgresql-username: guacamole_user
postgresql-password: XXXXX
postgresql-database: guacamole_db
postgresql-hostname: postgres
postgresql-port: 5432
ldap-hostname: 192.168.55.1
ldap-user-base-dn: OU=ruta,DC=dominio,DC=local
ldap-port: 389
ldap-encryption-method: none
ldap-search-bind-dn: cn=usuario_LDAP,OU=ruta,DC=dominio,DC=local
ldap-search-bind-password: CONTRASEÑA
ldap-username-attribute: samAccountName
ldap-config-base-dn: OU=ruta,DC=dominio,DC=local
Ahora ya solo falta crear un usuario en Apache Guacamole con el mismo nombre de usuario que en el Active Directory o LDAP y no ponerle contraseña y a funcionar!
Doble factor en Guacamole
En Guacamole existen dos formas de gestión de la autenticación en dos pasos (2FA). En nuestro caso, hemos activado extensión de autenticación TOTP que permite que los usuarios sean verificados adicionalmente contra una clave secreta y específica del usuario generada durante el registro de su dispositivo de autenticación. Es el mismo sistema que ya he explicado en otro post para ponerlo en Facebook, Instagram, Twitter mediante Microsoft Authenticator.
Para activarlo para todos los usuarios, únicamente hay que añadir TOTP_ENABLED: ‘true’ en el fichero docker-compose.yml en la sección de Guacamole:
...
guacamole:
container_name: guacamole_compose
depends_on:
- guacd
- postgres
environment:
GUACD_HOSTNAME: guacd
POSTGRES_DATABASE: guacamole_db
POSTGRES_HOSTNAME: postgres
POSTGRES_PASSWORD: ChooseYourOwnPasswordHere1234
POSTGRES_USER: guacamole_user
TOTP_ENABLED: 'true'
LDAP_HOSTNAME: DIRECCIÓN_IP_CONTROLADOR_DE_DOMINIO
LDAP_PORT: 389 # O seguro: 636
LDAP_USER_BASE_DN: OU=ruta,DC=dominio,DC=local
LDAP_USERNAME_ATTRIBUTE: samAccountName
LDAP_CONFIG_BASE_DN: OU=ruta,DC=dominio,DC=local
LDAP_ENCRYPTION_METHOD: none # O seguro: ssl, starttls
LDAP_SEARCH_BIND_DN: cn=usuario_LDAP,OU=ruta,DC=dominio,DC=local
LDAP_SEARCH_BIND_PASSWORD:CONTRASEÑA
image: guacamole/guacamole
links:
- guacd
networks:
guacnetwork_compose:
ports:
- 8080/tcp
restart: always
...
Cambiar guacadmin
Y por supuesto, OBLIGATORIO crear otro usuario administrador que no sea guacadmin o cambia la contraseña por defecto guacadmin por otra. Si yo accediese a un Guacamole ajeno, lo primero que probaría seria guacadmin / guacadmin.
Enlaces
- http://guacamole.incubator.apache.org/
- https://www.bujarra.com/autenticacion-de-apache-guacamole-contra-directorio-activo/
- https://guacamole.apache.org/doc/0.9.10-incubating/gug/guacamole-docker.html#guacamole-docker-ldap
- https://github.com/boschkundendienst/guacamole-docker-compose
- https://www.docker.com/
4 respuestas a “Autentica Guacamole contra LDPA o Active Directory con Docker Compose”
Buenas Javier, necesitaría una mano con este tema, llevo mucho tiempo intentando configurar el apache con el AD pero no lo doy conseguido, es algo que necesito ya que mi proyecto de fin de ciclo utiliza esta tecnología, podrías echarme una mano?
Gracias de antemano.
Hola, mándame un correo a ver si puedo echarte una mano.
Buenos dias, logre autenticar con el AD lo que queria preguntar haber si me pueden ayudar es como podria personalizar la pagina de inicio de guacamole es decir ponerle un fondo y en vez que diga APACHE GUACAMOLE poner otro texto en el formulario, intente pero no logro saber adonde buscar los archivos a editar. desde ya muchas gracias
Hola Gabriel,
Si no recuerdo mal, en /etc/guacamole/ debe existir un fichero llamado guacamole.properties. Puedes modificarlo con
sudo nano /etc/guacamole/guacamole.properties
Luego, tendrás que buscar la línea con la propiedad guacd-message, que pondrá:
guacd-message: Bienvenido a Apache Guacamole. Ingrese sus credenciales para comenzar.
Y podrás cambiarlo por tu mensaje, como por ejemplo:
guacd-message: ¡Hola! Te damos la bienvenida a nuestra plataforma de acceso remoto.
Guarda el fichero y luego reinicia el servicio con
sudo systemctl restart guacd