CentOS 7: Installation de Guacamole 0.9.9 et d'un Reverse Proxy Apache

De Pegasus45

Guacamole est une passerelle Web pour accéder à des serveurs ou des postes clients à distance. Il supporte les protocoles SSH, VNC et RDP. Il n'y aucun plugin à installer sur son poste. Grâce à HTML5, une fois que Guacamole a été installé sur un serveur, tout ce qu'on a besoin pour accéder à ces serveurs, c'est un navigateur Web.

La gestion des utilisateurs peut se faire dans un fichier XML (cas de cet article), dans une base de données SQL ou dans un annuaire LDAP.

Et il est gratuit et Open Source.


Pré-requis

Sur un serveur CentOS 7, on installe les pré-requis pour installer Guacammole:

Command
yum -y install wget gcc epel-release

yum -y install cairo-devel libjpeg-turbo-devel libpng-devel uuid-devel freerdp-devel pango-devel libssh2-devel libvncserver-devel openssl-devel libvorbis-devel libwebp-devel terminus-fonts

Installation de Tomcat

Guacamole s'installe sur un serveur Tomcat. On installe donc les paquets:

Command
yum install tomcat tomcat-admin-webapps tomcat-webapps

Et on déclare un compte d'Administration pour la gestion de Tomcat:

Configuration File vi /etc/tomcat/tomcat-users.xml
<tomcat-users>
  <role rolename="admin"/>
  <user username="admin" password="tomcat45" roles="admin,manager,admin-gui,admin-script,manager-gui,manager-script,manager-jmx,manager-status"/>
</tomcat-users>

On active et on relance Tomcat:

Command
systemctl enable tomcat
systemctl start tomcat

Si tout va bien, on doit pouvoir accéder à la page d'accueil de Tomcat: http://guacamole01:8080/


Installation de guacamole-server

Guacamole est compose de 2 parties:

  • guacamole-server (guacd) est un daemon qui sert de proxy entre le client (application Java installé dans Tomcat) et les serveurs distants,
  • guacamole-client est une application Java qui sera installée dans Tomcat et qui sera la partie visible (Web HTML5) pour l'utilisateur.

On commence par installer guacamole-server:

Command
mkdir ~/guacamole && cd ~/guacamole
wget http://downloads.sourceforge.net/project/guacamole/current/source/guacamole-server-0.9.9.tar.gz
tar zxvf guacamole-server-0.9.9.tar.gz
cd guacamole-server-0.9.9
./configure --with-init-dir=/etc/init.d
make
make install
ldconfig
chkconfig guacd on

Installation de guacamole-client

Maintenant, on récupère le fichier war et on l'installe dans Tomcat:

Command
cd ~/guacamole
wget http://downloads.sourceforge.net/project/guacamole/current/binary/guacamole-0.9.9.war
cp guacamole-0.9.9.war /var/lib/tomcat/webapps/
systemctl restart tomcat

mkdir -p /etc/guacamole/

Configuration de Guacamole

On configure guacamole-client pour qu'il puisse se connecter au daemon guacd:

Configuration File vi /etc/guacamole/guacamole.properties
# Hostname and port of guacamole proxy
guacd-hostname: localhost
guacd-port:     4822

# Location to read extra .jar's from
lib-directory:  /var/lib/tomcat/webapps/guacamole-0.9.9/WEB-INF/classes

# Authentication provider class
auth-provider: net.sourceforge.guacamole.net.basic.BasicFileAuthenticationProvider

# Properties used by BasicFileAuthenticationProvider
basic-user-mapping: /etc/guacamole/user-mapping.xml

Par défaut, l'application Java va chercher le fichier "guacamole.properties" dans le répertoire ".guacamole" dans l'utilisateur exécutant Tomcat. En regardant le fichier /etc/passwd, on voit que le homedir de l'utilisateur tomcat est /usr/share/tomcat. On va donc créer un lien symbolique dans son homedir pour qu'il pointe vers le fichier "guacamole.properties" qu'on vient de créer:

Command
mkdir /usr/share/tomcat/.guacamole
ln -s /etc/guacamole/guacamole.properties /usr/share/tomcat/.guacamole


Configuration des utilisateurs

Maintenant, on est prêt pour déclarer des utilisateurs ainsi qu'une liste de serveurs qu'ils pourront accéder. Ici, on va utiliser un simple fichier XML. On peut mettre leur mot de passe en clair ou bien indiquer un hash MD5:

Command
echo -n "secret_complique" | md5sum
=====================================================
b1202f8234fb2998f2a86a2903ef0fcc   -
=====================================================

On peut modifier le fichier XML:

Configuration File vi /etc/guacamole/user-mapping.xml
<user-mapping>
  <authorize
       username="daniel"
       password="b1202f8234fb2998f2a86a2903ef0fcc"
       encoding="md5">

        <!-- First authorized connection -->
        <connection name="localhost">
            <protocol>ssh</protocol>
            <param name="hostname">localhost</param>
            <param name="port">22</param>
        </connection>

        <!-- Second authorized connection -->
        <connection name="otherhost">
            <protocol>rdp</protocol>
            <param name="hostname">win2012</param>
            <param name="security">rdp</param>
        </connection>
  </authorize>

  <authorize username="USERNAME" password="PASSWORD">
        <protocol>vnc</protocol>
        <param name="hostname">localhost</param>
        <param name="port">5900</param>
        <param name="password">VNCPASS</param>
   </authorize>
</user-mapping>

On peut relancer les services:

Command
systemctl restart tomcat
systemctl start guacd


Installation de Reverse Proxy Apache

On va installer Apache en tant que Reverse Proxy (entre les utilisateurs et Guacamole) et on sécurise les communications avec du HTTPS. De plus, comme le serveur sera visible sur Internet, je ferais un contrôle de certificat Client SSL. Seuls les utilisateurs ayant un certificat Client SSL valide pourront accéder à la page de login de Guacamole.

La création d'une PKI et des certificats pour Apache et les clients sont détaillés dans l'article CentOS7: private PKI : Introduction.

On installe Apache:

Command
yum install httpd mod_ssl
systemctl enable httpd
cd /etc/httpd/conf.d/
mv ssl.conf ssl.conf_ori

On configure le VirtualHost pour l'écoute du port 443:

Configuration File vi ssl.conf
Listen 443 https

SSLPassPhraseDialog exec:/usr/libexec/httpd-ssl-pass-dialog
SSLSessionCache         shmcb:/run/httpd/sslcache(512000)
SSLSessionCacheTimeout  300
SSLRandomSeed startup file:/dev/urandom  256
SSLRandomSeed connect builtin
SSLCryptoDevice builtin

<VirtualHost _default_:443>
        ServerName www.pegasus45.lan

        ErrorLog logs/ssl_error_log
        TransferLog logs/ssl_access_log
        LogLevel warn
        SetEnvIf Request_URI "^/guacamole/tunnel" dontlog
        
        SSLEngine on
        SSLProtocol all -SSLv3 -TLSv1 -TLSv1.1
        SSLCipherSuite          ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256
        SSLHonorCipherOrder     on
        SSLCompression          off

        SSLCertificateFile      /etc/httpd/certs/www.pegasus45.lan.cert.pem
        SSLCertificateKeyFile   /etc/httpd/certs/www.pegasus45.lan.nokey.pem
        SSLCACertificateFile    /etc/httpd/certs/ca-chain.cert.pem

        SSLVerifyClient 		require
        SSLVerifyDepth  		10
	SSLCARevocationFile     /etc/httpd/certs/intermediate.crl.pem
        # Car j'utilise une PKI privée, non reconnue sur Internet, j'utilise leaf
        SSLCARevocationCheck    leaf

        <Location />
            SSLRequire (    %{SSL_CIPHER} !~ m/^(EXP|NULL)/ \
                and %{SSL_CLIENT_S_DN_O} eq "Pegasus45" \
                and %{SSL_CLIENT_S_DN_CN} =~ m/([a-z|A-Z]){3,25}@pegasus45\.lan/ \
                and %{TIME_WDAY} >= 1 and %{TIME_WDAY} <= 5 \
                and %{TIME_HOUR} >= 8 and %{TIME_HOUR} <= 20  ) 
        </Location>


        <Files ~ "\.(cgi|shtml|phtml|php3?)$">
            SSLOptions +StdEnvVars
        </Files>
        <Directory "/var/www/cgi-bin">
            SSLOptions +StdEnvVars
        </Directory>

        BrowserMatch "MSIE [2-5]" \
            nokeepalive ssl-unclean-shutdown \
            downgrade-1.0 force-response-1.0

        CustomLog logs/ssl_request_log \
          "%t %h %{SSL_PROTOCOL}x %{SSL_CIPHER}x \"%r\" %b" env=!dontlog

        <Location /guacamole/>
            Order allow,deny
            Allow from all
            ProxyPass http://127.0.0.1:8080/guacamole-0.9.9/ flushpackets=on
            ProxyPassReverse http://127.0.0.1:8080/guacamole-0.9.9/
            ProxyPassReverseCookiePath /guacamole-0.9.9/ /guacamole/
        </Location>

        <Location /guacamole/websocket-tunnel>
            Order allow,deny
            Allow from all
            ProxyPass ws://127.0.0.1:8080/guacamole/websocket-tunnel
            ProxyPassReverse ws://127.0.0.1:8080/guacamole/websocket-tunnel
        </Location>
</VirtualHost>

On modifie la conf du fichier httpd.conf:

Configuration File vi /etc/httpd/conf/httpd.conf
(à ajouter)
ServerTokens Prod
ServerSignature Off

(à modifier)
#Listen 80
ServerName guacamole01.perso.lan

Et on relance Apache:

Command
systemctl restart httpd