Qu’est-ce qu’un bastion ?
Un bastion, comme Apache Guacamole, est une machine (virtualisée ou non) qui sert de point d’accès sécurisé pour se connecter aux autres systèmes d’une infrastructure informatique.
Il joue un rôle crucial en matière de sécurité, car il permet de concentrer, contrôler et sécuriser les accès aux systèmes critiques : serveurs, bases de données ou toute autre ressource sensible.
| Apport | Ce que cela signifie |
|---|---|
| Contrôle d’accès centralisé | Le bastion est la porte d’entrée unique vers les systèmes internes. |
| Amélioration de la sécurité | Les accès peuvent être surveillés, enregistrés et filtrés. |
| Traçabilité et audit | Les connexions sont journalisées, et les sessions peuvent être enregistrées puis relues. |
| Simplification des accès distants | Guacamole fonctionne depuis un navigateur, sans client à installer. |
| Réduction des risques de configuration | L’interface web limite les erreurs de configuration côté poste client. |
Le serveur Apache Guacamole sera le point d’entrée unique pour accéder aux serveurs et équipements de l’infrastructure, via les protocoles RDP, SSH, VNC et même Kubernetes. Que l’on soit en externe ou en interne, les connexions aux serveurs passeront obligatoirement par l’hôte Guacamole.
Où positionner le bastion ?
Positionner un bastion nécessite une réflexion stratégique pour assurer la sécurité, la disponibilité et la performance des accès à distance.
Segment réseau isolé ou DMZ
Le bastion doit idéalement être placé dans une zone démilitarisée (DMZ), segment tampon entre le réseau interne et l’extérieur, ce qui limite l’exposition directe du réseau interne.
Pourquoi ? La DMZ permet de contrôler les flux entrants et sortants et fournit une couche de protection supplémentaire en cas de compromission du bastion : seuls les services strictement nécessaires sont accessibles.
Contrôle d’accès via un pare-feu
En plaçant le bastion derrière un pare-feu entre la DMZ et le réseau interne, on restreint l’accès aux ressources internes aux seuls ports et protocoles nécessaires.
Pourquoi ? Tous les accès passent par une couche de filtrage et de surveillance, ce qui limite les risques d’intrusion.
Connexion sécurisée par VPN ou tunnel SSH
Depuis l’extérieur, l’accès au bastion ne doit être possible qu’au travers d’un VPN ou d’un tunnel SSH.
Pourquoi ? Ces connexions ajoutent une couche de chiffrement et d’authentification, et évitent d’exposer directement le portail web sur Internet.
Accès restreint aux réseaux internes
Le bastion ne doit atteindre que les sous-réseaux ou machines nécessaires, grâce à des règles de pare-feu internes.
Pourquoi ? En limitant ses permissions, on réduit la surface d’attaque et on contrôle la propagation en cas de compromission.
Authentification multifacteur (MFA) et journalisation
La MFA et des journaux d’accès détaillés sont essentiels sur le bastion (mis en œuvre plus bas, section « Sécuriser le bastion »).
Pourquoi ? La MFA garantit que seules les personnes autorisées accèdent au bastion ; les journaux permettent de tracer toute activité suspecte ou anormale.
Architecture cible et prérequis
Tous les composants sont installés sur la même machine Debian 12. Seul Nginx est joignable depuis le réseau ; les autres services n’écoutent que localement.
| Composant | Rôle | Écoute |
|---|---|---|
| Nginx | Reverse proxy HTTPS : seule porte d’entrée web du bastion | 0.0.0.0:443 (et 80 → redirection) |
| Tomcat 9 | Exécute l’application web Guacamole (fichier .war) | 127.0.0.1:8080 |
| guacd | Démon qui ouvre les connexions RDP / SSH / VNC vers les serveurs | 127.0.0.1:4822 |
| MariaDB | Stocke utilisateurs, droits, connexions et historique | 127.0.0.1:3306 |
| Élément | Version utilisée | Où vérifier |
|---|---|---|
| Debian | 12 « bookworm » (LTS jusqu’en juin 2028) | debian.org/releases |
| Apache Guacamole | 1.6.0 (22 juin 2025) | guacamole.apache.org/releases |
| Tomcat | 9.0.122 (archive officielle Apache) | tomcat.apache.org/download-90.cgi |
| Java | OpenJDK 17 (dépôts Debian 12) | — |
| MySQL Connector/J | 9.7.0 (avril 2026) | dev.mysql.com/downloads/connector/j |
Toutes les commandes s’exécutent avec des droits d’administration (root ou sudo). C’est une nécessité pour installer des paquets et des services, pas une bonne pratique en soi : une fois le bastion en place, on n’utilise plus root au quotidien.
Préparer le système
On met le système à jour, puis on installe les dépendances de compilation. La liste complète est dans la documentation officielle d’installation d’Apache Guacamole.
apt-get update && apt-get upgrade -y
apt-get install -y build-essential libcairo2-dev libjpeg62-turbo-dev libpng-dev \
libtool-bin uuid-dev libossp-uuid-dev libavcodec-dev libavformat-dev \
libavutil-dev libswscale-dev freerdp2-dev libpango1.0-dev libssh2-1-dev \
libvncserver-dev libwebsockets-dev libpulse-dev libssl-dev libvorbis-dev \
libwebp-dev
Compiler et installer guacd (Guacamole Server)
A. Télécharger et vérifier les sources
On fixe la version dans une variable, réutilisée dans toute la suite. Si vous ouvrez un nouveau terminal, redéfinissez-la.
VER=1.6.0
cd /tmp
wget https://downloads.apache.org/guacamole/${VER}/source/guacamole-server-${VER}.tar.gz
wget https://downloads.apache.org/guacamole/${VER}/source/guacamole-server-${VER}.tar.gz.sha256
sha256sum guacamole-server-${VER}.tar.gz
cat guacamole-server-${VER}.tar.gz.sha256
B. Configurer et compiler
tar -xzf guacamole-server-${VER}.tar.gz
cd guacamole-server-${VER}/
./configure --with-systemd-dir=/etc/systemd/system/
En fin de sortie, on contrôle le support des protocoles. Résultat attendu :
Protocol support:
Kubernetes .... yes
RDP ........... yes
SSH ........... yes
Telnet ........ no <- voulu
VNC ........... yes
Services / tools:
guacd ...... yes
make -j"$(nproc)"
make install
ldconfig
C. Configurer guacd en écoute locale
mkdir -p /etc/guacamole/{extensions,lib}
nano /etc/guacamole/guacd.conf
[server]
bind_host = 127.0.0.1
bind_port = 4822
D. Donner un répertoire de travail à guacd
guacd tourne sous le compte système daemon, dont le répertoire personnel n’est pas modifiable. Or, pour les connexions RDP, la bibliothèque FreeRDP a besoin d’y écrire sa configuration : sans répertoire accessible, les connexions RDP échouent (en particulier avec NLA). On lui attribue un répertoire dédié par une surcharge systemd, sans modifier le fichier de service installé.
mkdir -p /etc/systemd/system/guacd.service.d
nano /etc/systemd/system/guacd.service.d/override.conf
[Service]
StateDirectory=guacd
Environment=HOME=/var/lib/guacd
E. Démarrer guacd
systemctl daemon-reload
systemctl enable --now guacd
systemctl status guacd
systemctl show guacd -p Environment
Le statut doit être active (running), avec la ligne Listening on host 127.0.0.1, port 4822. La dernière commande doit afficher Environment=HOME=/var/lib/guacd. Le service tourne sous le compte système daemon, pas en root.
Installer Tomcat 9 et l’application web
Guacamole 1.6.0 s’exécute sur Tomcat 9. Tomcat 10, fourni par Debian 12, utilise une autre API Java (jakarta.servlet au lieu de javax.servlet) : le projet Guacamole ne le prendra en charge qu’à partir de sa version 2.0.0. Debian 12 ne proposant plus Tomcat 9, on l’installe depuis l’archive officielle d’Apache, sans dépôt tiers ni conversion.
A. Installer Java et créer le compte de service
Tomcat tourne sous un compte système dédié, sans shell ni droit de connexion : jamais en root.
apt-get install -y openjdk-17-jre-headless
useradd --system --user-group --home-dir /opt/tomcat --shell /usr/sbin/nologin tomcat
B. Télécharger et vérifier Tomcat
Vérifiez la dernière version 9.0.x sur la page de téléchargement officielle d’Apache Tomcat 9.
TOMCAT_VER=9.0.122
cd /tmp
wget https://downloads.apache.org/tomcat/tomcat-9/v${TOMCAT_VER}/bin/apache-tomcat-${TOMCAT_VER}.tar.gz
wget https://downloads.apache.org/tomcat/tomcat-9/v${TOMCAT_VER}/bin/apache-tomcat-${TOMCAT_VER}.tar.gz.sha512
sha512sum -c apache-tomcat-${TOMCAT_VER}.tar.gz.sha512
La dernière commande doit afficher « Réussi » (ou « OK »). Sinon, on n’installe pas l’archive.
C. Installer Tomcat
On installe Tomcat dans /opt/tomcat, avec un lien latest vers la version en service : une mise à jour consistera à faire pointer ce lien vers la nouvelle version.
mkdir -p /opt/tomcat
tar -xzf apache-tomcat-${TOMCAT_VER}.tar.gz -C /opt/tomcat
ln -sfn /opt/tomcat/apache-tomcat-${TOMCAT_VER} /opt/tomcat/latest
# Applications livrées par défaut : inutiles sur un bastion
rm -rf /opt/tomcat/latest/webapps/*
# Binaires et configuration : propriété de root, lisibles par le groupe tomcat
chown -R root:tomcat /opt/tomcat/apache-tomcat-${TOMCAT_VER}
chmod -R g+rX,o-rwx /opt/tomcat/apache-tomcat-${TOMCAT_VER}
# Seuls ces répertoires sont modifiables par Tomcat
mkdir -p /opt/tomcat/latest/conf/Catalina/localhost
chown -R tomcat:tomcat /opt/tomcat/latest/{logs,temp,work,webapps,conf/Catalina}
D. Créer le service systemd
nano /etc/systemd/system/tomcat.service
[Unit]
Description=Apache Tomcat 9 (Guacamole)
After=network.target
[Service]
Type=simple
User=tomcat
Group=tomcat
Environment="JAVA_HOME=/usr/lib/jvm/java-17-openjdk-amd64"
Environment="CATALINA_HOME=/opt/tomcat/latest"
Environment="CATALINA_BASE=/opt/tomcat/latest"
Environment="GUACAMOLE_HOME=/etc/guacamole"
ExecStart=/opt/tomcat/latest/bin/catalina.sh run
UMask=0027
NoNewPrivileges=true
PrivateTmp=true
Restart=on-failure
[Install]
WantedBy=multi-user.target
systemctl daemon-reload
systemctl enable --now tomcat
systemctl status tomcat
GUACAMOLE_HOME indique explicitement à Guacamole où trouver sa configuration (/etc/guacamole). NoNewPrivileges et PrivateTmp durcissent le service.
E. Déployer l’application web Guacamole
cd /tmp
wget https://downloads.apache.org/guacamole/${VER}/binary/guacamole-${VER}.war
install -o tomcat -g tomcat -m 640 guacamole-${VER}.war /opt/tomcat/latest/webapps/guacamole.war
systemctl restart tomcat
Base de données MariaDB
Une base de données permet de gérer utilisateurs et permissions, de conserver l’historique des connexions (audit, conformité) et de s’intégrer à un annuaire LDAP / Active Directory. Guacamole prend en charge MySQL / MariaDB et PostgreSQL ; on utilise ici MariaDB.
A. Installer et sécuriser MariaDB
apt-get install -y mariadb-server
mariadb-secure-installation
Le script supprime les comptes anonymes et la base de test, et interdit la connexion root à distance. Sur Debian, root se connecte ensuite simplement avec la commande mariadb (authentification par socket local).
B. Créer la base et le compte applicatif
On génère d’abord un mot de passe fort :
openssl rand -base64 24
-- dans la console : mariadb
CREATE DATABASE bastion_db CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER 'bastion_app'@'localhost' IDENTIFIED BY '<MotDePasseFort>';
GRANT SELECT,INSERT,UPDATE,DELETE ON bastion_db.* TO 'bastion_app'@'localhost';
FLUSH PRIVILEGES;
EXIT;
C. Extension JDBC et import du schéma
cd /tmp
wget https://downloads.apache.org/guacamole/${VER}/binary/guacamole-auth-jdbc-${VER}.tar.gz
tar -xzf guacamole-auth-jdbc-${VER}.tar.gz
cat guacamole-auth-jdbc-${VER}/mysql/schema/*.sql | mariadb bastion_db
cp guacamole-auth-jdbc-${VER}/mysql/guacamole-auth-jdbc-mysql-${VER}.jar /etc/guacamole/extensions/
D. Connecteur MySQL (Connector/J)
Le connecteur se télécharge sur le site de MySQL, que l’on utilise MariaDB ou MySQL. Vérifiez la dernière version (Platform Independent, archive .tar.gz) sur la page de téléchargement de MySQL Connector/J.
JDBC_VER=9.7.0
cd /tmp
wget https://dev.mysql.com/get/Downloads/Connector-J/mysql-connector-j-${JDBC_VER}.tar.gz
tar -xzf mysql-connector-j-${JDBC_VER}.tar.gz
cp mysql-connector-j-${JDBC_VER}/mysql-connector-j-${JDBC_VER}.jar /etc/guacamole/lib/
E. Fichier guacamole.properties
nano /etc/guacamole/guacamole.properties
# guacd
guacd-hostname: 127.0.0.1
guacd-port: 4822
# MariaDB
mysql-hostname: 127.0.0.1
mysql-port: 3306
mysql-database: bastion_db
mysql-username: bastion_app
mysql-password: <MotDePasseFort>
Ce fichier contient un mot de passe en clair : seuls root et Tomcat doivent pouvoir le lire.
chown root:tomcat /etc/guacamole/guacamole.properties
chmod 640 /etc/guacamole/guacamole.properties
systemctl restart tomcat
Publier le bastion en HTTPS
Par défaut, Tomcat sert Guacamole en clair sur le port 8080 : identifiants et sessions circuleraient sans chiffrement. On place Nginx devant, en HTTPS, et on ferme Tomcat au réseau.
A. Tomcat en écoute locale et vraie IP des clients
nano /opt/tomcat/latest/conf/server.xml
Dans le connecteur HTTP (port 8080), on ajoute l’attribut address ; les autres attributs présents restent tels quels :
<Connector port="8080" protocol="HTTP/1.1"
address="127.0.0.1"
connectionTimeout="20000"
redirectPort="8443" />
Puis, à l’intérieur de la balise <Host>, on ajoute la valve suivante. Sans elle, Tomcat verrait toutes les connexions venir de 127.0.0.1 (Nginx) : l’historique serait inexploitable et l’anti-force brute bannirait le proxy lui-même.
<Valve className="org.apache.catalina.valves.RemoteIpValve"
internalProxies="127\.0\.0\.1|0:0:0:0:0:0:0:1"
remoteIpHeader="x-forwarded-for"
remoteIpProxiesHeader="x-forwarded-by"
protocolHeader="x-forwarded-proto" />
B. Certificat TLS
Pour la maquette, on génère un certificat autosigné (le navigateur affichera un avertissement). En production, on utilise un certificat émis par l’autorité de certification interne de l’entreprise.
apt-get install -y nginx
mkdir -p /etc/nginx/ssl
openssl req -x509 -nodes -newkey rsa:3072 -days 825 \
-keyout /etc/nginx/ssl/guacamole.key -out /etc/nginx/ssl/guacamole.crt \
-subj "/CN=bastion.mondomaine.local" \
-addext "subjectAltName=DNS:bastion.mondomaine.local,IP:192.168.99.12"
chmod 600 /etc/nginx/ssl/guacamole.key
C. Site Nginx
nano /etc/nginx/sites-available/guacamole
server {
listen 80;
server_name bastion.mondomaine.local;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl http2;
server_name bastion.mondomaine.local;
ssl_certificate /etc/nginx/ssl/guacamole.crt;
ssl_certificate_key /etc/nginx/ssl/guacamole.key;
ssl_protocols TLSv1.2 TLSv1.3;
location = / { return 301 /guacamole/; }
location /guacamole/ {
proxy_pass http://127.0.0.1:8080;
proxy_buffering off;
proxy_http_version 1.1;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $http_connection;
access_log off;
}
}
ln -s /etc/nginx/sites-available/guacamole /etc/nginx/sites-enabled/
rm /etc/nginx/sites-enabled/default
nginx -t && systemctl restart nginx tomcat
Le bastion est accessible sur https://bastion.mondomaine.local/guacamole/.
Sécuriser le bastion
A. Remplacer le compte par défaut
Le schéma de base crée un administrateur guacadmin / guacadmin, connu de tous. À faire immédiatement, avant toute autre configuration :
- Se connecter avec
guacadmin/guacadmin. - Paramètres → Utilisateurs → Nouvel utilisateur : créer un compte administrateur nominatif, lui cocher toutes les permissions d’administration.
- Se déconnecter, se reconnecter avec ce nouveau compte.
- Supprimer le compte
guacadmin.
B. Double authentification, anti-force brute et enregistrement des sessions
Trois extensions officielles complètent le dispositif. Elles se téléchargent depuis le dépôt officiel et se copient dans /etc/guacamole/extensions/ :
| Extension | Rôle |
|---|---|
guacamole-auth-totp | Double authentification par code à usage unique (application d’authentification sur smartphone). |
guacamole-auth-ban | Bloque temporairement une adresse IP après plusieurs échecs de connexion. Activée d’office avec Docker, mais à installer à la main ici. |
guacamole-history-recording-storage | Permet de relire les sessions enregistrées directement dans l’historique de l’interface web. |
cd /tmp
for EXT in auth-totp auth-ban history-recording-storage; do
wget https://downloads.apache.org/guacamole/${VER}/binary/guacamole-${EXT}-${VER}.tar.gz
tar -xzf guacamole-${EXT}-${VER}.tar.gz
cp guacamole-${EXT}-${VER}/guacamole-${EXT}-${VER}.jar /etc/guacamole/extensions/
done
On crée le répertoire des enregistrements : guacd (compte daemon) y écrit, Tomcat y lit.
mkdir -p /var/lib/guacamole/recordings
chown daemon:tomcat /var/lib/guacamole/recordings
chmod 2750 /var/lib/guacamole/recordings
On ajoute à la fin de /etc/guacamole/guacamole.properties (valeurs par défaut, affichées pour être explicites) :
# Double authentification
totp-issuer: Bastion BTS SIO
# Anti-force brute : 5 échecs = 5 minutes de blocage
ban-max-invalid-attempts: 5
ban-address-duration: 300
systemctl restart tomcat
À la connexion suivante, chaque utilisateur doit scanner un QR code avec une application d’authentification, puis saisir le code à 6 chiffres à chaque connexion.
Pour enregistrer les sessions d’une connexion : dans ses paramètres, section Enregistrement d’écran, renseigner :
| Paramètre | Valeur |
|---|---|
| Chemin de l’enregistrement | ${HISTORY_PATH}/${HISTORY_UUID} |
| Créer automatiquement le chemin | coché |
| Nom de l’enregistrement | par exemple session-${GUAC_DATE}-${GUAC_TIME} |
C. Pare-feu local (nftables)
Même derrière le pare-feu de la DMZ, le bastion filtre lui-même ses flux entrants : défense en profondeur. Adaptez le réseau des postes d’administration autorisés en SSH.
apt-get install -y nftables
nano /etc/nftables.conf
#!/usr/sbin/nft -f
flush ruleset
table inet filter {
chain input {
type filter hook input priority 0; policy drop;
iif "lo" accept
ct state established,related accept
ct state invalid drop
ip protocol icmp accept
ip6 nexthdr icmpv6 accept
tcp dport { 80, 443 } accept
ip saddr 192.168.50.0/24 tcp dport 22 accept # postes admin (à adapter)
}
chain forward {
type filter hook forward priority 0; policy drop;
}
}
nft -c -f /etc/nftables.conf
systemctl enable --now nftables
Vérifications finales
ss -tlnp
Résultat attendu (extrait) : seuls Nginx et SSH écoutent sur toutes les interfaces.
LISTEN 0.0.0.0:443 users:(("nginx",...))
LISTEN 0.0.0.0:80 users:(("nginx",...))
LISTEN 0.0.0.0:22 users:(("sshd",...))
LISTEN 127.0.0.1:8080 users:(("java",...))
LISTEN 127.0.0.1:8005 users:(("java",...)) <- arrêt de Tomcat
LISTEN 127.0.0.1:4822 users:(("guacd",...))
LISTEN 127.0.0.1:3306 users:(("mariadbd",...))
| Contrôle | Attendu |
|---|---|
http:// + adresse du bastion | Redirection automatique vers HTTPS |
http://<IP>:8080 depuis un autre poste | Connexion refusée |
Connexion avec guacadmin | Refusée : le compte n’existe plus |
| Connexion avec le compte nominatif | Mot de passe puis code TOTP demandés |
| 6 mots de passe faux depuis un poste | Adresse IP bloquée pendant 5 minutes |
| Session RDP / SSH vers un serveur | Fonctionne ; relecture possible dans Historique |
Source d’origine : IT-Connect, procédure adaptée et mise à jour d’après la documentation officielle Apache Guacamole 1.6.0. Relecture du 29 septembre 2026.
🧠 Testez vos connaissances
6 questions. Répondez puis cliquez sur « Corriger ». Rien n’est enregistré : c’est de l’auto-évaluation.
Ce cours adapte une procédure publiée par un tiers (voir la source en fin de page) : il n’est pas couvert par la licence CC BY-NC-SA 4.0 du site. Tous droits réservés à leurs auteurs respectifs.