Accéder à son infra de partout: Un bastion Guacamole

Dans cet article on va parler de comment mettre en place un bastion pour accéder à chez soi de manière sécurisée avec Apache Guacamole et Docker

Accéder à son infra de partout: Un bastion Guacamole
Photo by Tessa Rampersad / Unsplash

J'ai toujours aimé la cuisine mexicaine mais là je dois dire que j'ai peut être trouvé mon plat préféré. Republier après de longs mois d'absence et commencer par une blague nulle pourquoi pas ? Dans cet article on va parler de comment mettre en place un bastion pour accéder à chez soi de manière sécurisée avec Apache Guacamole.

Un bastion si on veut résumer c'est une porte d'entrée sur une infrastructure qui gère les droits d'accès de chacun. Dans notre cas la porte d’entrée sur le homelab qui va nous permettre de nous connecter à une machine de rebond de laquelle vous ferez ce que vous voulez. Par défaut Guacamole gère VNC, RDP et SSH ce qui reste largement suffisant pour couvrir 90% des usages.

On trouve des tutos pour installer Guacamole directement sur un serveur Next en a d'ailleurs publié un très bien récemment. Seulement entre les versions qui ne fonctionnent pas, les erreurs de compilations sans explication et autres joyeusetés j'ai pris le chemin de l'image Docker très vite. On se retrouve donc avec une stack composée de guacd qui est le démon Guacamole qui se charge de gérer les connexions, un conteneur pour gérer le front-end et une db pour stocker users et sessions.

version: '3.6'

services:
  guacd:
    container_name: guacamole_backend
    image: guacamole/guacd
    restart: always
    volumes:
    - ./drive:/drive:rw
    - ./record:/var/lib/guacamole/recordings:rw

  postgres:
    container_name: guacamole_database
    environment:
      PGDATA: /var/lib/postgresql/data/guacamole
      POSTGRES_DB: guacamole_db
      POSTGRES_PASSWORD: motdepassedelabasepostgresql
      POSTGRES_USER: utilisateurdelabasepostgresql
    image: postgres:15.0
    restart: always
    volumes:
    - ./init:/docker-entrypoint-initdb.d:ro
    - ./data:/var/lib/postgresql/data:rw
    
  guacamole:
    container_name: guacamole_frontend
    depends_on:
    - guacd
    - postgres
    environment:
      WEBAPP_CONTEXT: 'ROOT'
      GUACD_HOSTNAME: guacd
      POSTGRESQL_DATABASE: guacamole_db
      POSTGRESQL_HOSTNAME: postgres
      POSTGRESQL_PASSWORD: motdepassedelabasepostgresql
      POSTGRESQL_USER: utilisateurdelabasepostgresql
      POSTGRESQL_AUTO_CREATE_ACCOUNTS: true
      TOTP_ENABLED: 'true'
    image: guacamole/guacamole
    restart: always
    ports:
      - 8080:8080
    volumes:
    - ./drive:/drive:rw
    - ./record:/var/lib/guacamole/recordings

Les volumes déclarés vont permettre d'assurer une fonctionnalité que la plupart des solutions similaires proposent: l'enregistrement des sessions. Cela permet de garder des traces de ce qui est fait sur une infra au fur et à mesure des interventions. Moins utile dans un cadre personnel ça l'est beaucoup plus dans le cadre professionnel.

Les variables d'environnement sont assez parlante néanmoins il est intéressant de revenir sur deux d'entre elles:

WEBAPP_CONTEXT: 'ROOT' Permet que l'application réponde sur mondomaine.com plutôt que mondomaine.com/guacamole/

TOTP_ENABLED: 'true'Active le support de l'authentification et vous permettra de configurer une application de gestion d'OTP

Une fois que vous êtes prêts plus qu'a lancer docker-compose up -d et le tour est joué!

Vous pouvez ensuite accéder a Guacamole via http://ipduserveur:8080/guacamole/ ou selon ce que vous avez configuré http://ipduserveur: 8080 . A la première connexion avec guacadmin/guacadmin changez le mot de passe et définissez un OTP si besoin. Vous pouvez ensuite créer vos connexions.

Pour faire les choses bien on peut gérer l'accès via un reverse proxy comme Nginx par exemple. Voici le bloc que j'utilise et qui fonctionne pas trop mal:

location / {
                proxy_pass http://192.168.X.Y:8080;
                proxy_buffering off;
                proxy_http_version 1.1;
                proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
                proxy_set_header Upgrade $http_upgrade;
                proxy_set_header Connection $http_connection;
                
        }