Menu Chiudi

exPillola #65: Gestione telelavoro tramite Guacamole

Schema di funzionamento generale
PC-SmartWork–>Internet–>Firewall–>ReverseProxy(per certificati LetsEncrypt)–>Guacamole–>Client-di-rete (tramite RDP o VNC)

I certificati LetsEncypt potrebbero essere installati direttamente su Guacamole ma avendo già in casa un reverse proxy ho preferito riutilizzare quello !

Installato tramite lo script recuperato a questo indirizzo (utilizzabile, tendenzialmente anche per futuri upgrade) su di una Debian Buster 10.3:

https://github.com/MysticRyuujin/guac-install/blob/master/README.md

Questo invece l’ho utilizzato per “customizzare” la maschera di login (per sostituire il logo di Guacamole nella login di accesso):

https://github.com/Zer0CoolX/guacamole-customize-loginscreen-extension

Esiste un modulo che consentirebbe di gestire l’autenticazione tramite LDAP ma ho preferito NON utilizzarlo per i seguenti motivi:
– preferisco avere diversi livelli di accesso per accedere alle postazioni visto che i client aziendali vengono esposti in qualche modo in rete
– il server Guacamole si trova in una DMZ e personalmente preferisco non concedergli l’accesso al server LDAP

Autenticazione a due fattori
L’estensione TOTP consente l’autenticazione degli utenti a due fattori.
Questo aumenta di molto la sicurezza ma ovviamente ha anche i suoi svantaggi:
– l’utente deve, oltre alla password, utilizzare il proprio palmare per l’autenticazione
– l’autenticazione a due livelli è per TUTTI gli utenti, anche per gli amministratori
– l’eventuale perdita o disinstallazione dell’app TOTP dal palmare comporta che lato server va alterato il contenuto del database per consentire la registrazione di un nuovo cellulare

/opt/localbin/resetTOTP.sh NOME_UTENTE

la password richiesta è quella dell'utente ROOT utilizzato per l'accesso a mysql

Questo lo script utilizzato per il reset TOTP

# cat /opt/localbin/resetTOTP.sh

#!/bin/bash

if [ “$#” != “1” ]
then
echo Usare $0 NOME_UTENTE
exit 0
fi
/usr/bin/mysql -u root -p guacamole_db -Bse “update guacamole_user_attribute set attribute_value = ‘false’ where attribute_name=’guac-totp-key-confirmed’ and user_id=(select user_id from guacamole_user where entity_id = (select entity_id from guacamole_entity where name=’$1′));”


Abilitazione di un nuovo utente/postazione

- su ogni postazione di lavoro va configurato remote desktop per accettare connessioni per ogni specifico utente di rete
- il profilo utente DEVE consentire la modifica della password altrimenti TOTP non funziona !!
- in guacamole va configurata una nuova connessione e va presa nota del NR di connessione creata (visibile nell'header)
- la connessione va configurata nel file /opt/localbin/macs.list indicando il MAC address del PC che verrà acceso tramite WOL
- l'utente deve installare sul proprio cellulare l'app "Sophos Autenticator" per l'autenticazione a due fattori tramite TOTP

Gestione del WOL
Per gestire l’accensione tramite WOL delle macchine viene utilizzato uno script python il quale,
in base al contenuto del file “/var/log/tomcat9/catalina.out” avvia tramite ssh un comando sui server “IL_MIO_GATEWAY_1” e “IL_MIO_GATEWAY_2” per l’accensione dei pc.

Questo il contenuto dello script lato IL_MIO_GATEWAY che si occupa di inviare il magic packet per il WOL dei client

# cat /opt/localbin/accendiPCSede.sh
#!/bin/bash
IP=$1

if [ “$1” = “” ]
then
echo Usare $0 MAC-ADDRESS
exit 0
fi

/usr/bin/sudo /usr/sbin/etherwake -D -i eth0 $1
echo Accensione PC $1
exit 0

Tramite il file /opt/localbin/macs.list vengono configurati i relativi MAC address connessi ai vari PC (connessioni in Guacamole).

Per consentire l’esecuzione del comando WOL sui vari gateway ho:
– creato un nuovo utente wol su guacamole e su tutti i gateway
– disattivato l’accesso tramite password per l’utente wol (passwd wol -l) su guacamole e su tutti i gateway
– creato le chiavi ssh per l’utente wol
– copiato le chiavi nei relativi file authorized_keys sui server gateway

# cat /home/wol/.ssh/authorized_keys
command="/opt/localbin/accendiPCSede.sh $SSH_ORIGINAL_COMMAND",no-port-forwarding,no-x11-forwarding,no-agent-forwarding ssh-rsa CIAVE_PUBBLICA wol@guacamole

– aggiunto la seguente riga a /etc/sudoers sui vari gateway

wol        ALL=NOPASSWD:    /usr/sbin/etherwake

– lato guacamole ho creato un nuovo servizio systemd

#cat /etc/systemd/system/guac_wol.service
[Unit]
Description=Servizio per lanciare un WOL non appena viene avviata una connessione tramite Apache Guacamole
ConditionPathExists=/opt/localbin/guac_wol.py

[Service]
ExecStart=/opt/localbin/guac_wol.py &
ExecStop=/usr/bin/killall tail
[Install]
WantedBy=multi-user.target
Alias=guac_wol.service

e attivato in questo modo:

systemctl enable guac_wol.service

questo il file che gestisce il WOL (recuperato da questo indirizzo http://mail-archives.apache.org/mod_mbox/guacamole-user/201802.mbox/%3C1… e riadattato per le mie esigenze).

# cat guac_wol.py
#!/usr/bin/env python2
#
# --------------------------Readme---------------------------------------
#
# Guacamole wake-on-lan (WOL) script. Luke P 26 Feb 2018
#
# This is designed to run on the Guac host machine and will send a
# 'magic-packet'wakeup call to a specified machine on the same
# network when a Guac connection attempt is made.
#
# Relies on Guac continually attempting a connect as most machines
# will not start up immediately (ie, there is no delay function from
# when the wakeup is sent to when Guac attempts a connect). Some
# machines may go through a full reconnect cycle before they fully
# wake up and a connection is established.
#
# Script reads a 'macs.list' file in the same directory as it runs from.
# File must contain only the header detail, and comma-separated fields
# of id (Guac connection number) and MAC addr. There is no error
# checking and it will likely fail if there are any other random
# characters in the file. Data from this file is compared to the
# ongoing connection data in /var/logs/tomcat7/catalina.out
# You would probably need to change this path if your system
# uses tomcat8.
#
# --- example macs.list --- #
# id,mac
# 1,11:22:33:44:55:66
# 2,22:33:44:55:66:77
# 3,33:44:55:66:77:88
# 4,44:55:66:77:88:99
# 5,55:66:77:88:99:00
# 6,66:77:88:99:00:aa
# etc,etc
# ----------------------------- #
#
# This is a rough 'n ready script and has not been tested for any length
# of time, nor on anything other than Guacamole 0.9.14 and Python 2.7 in
# Ubuntu 16.04. It is offered as a concept only, if you choose to try it
# and it works for you that's great, if it doesn't, or it somehow breaks
# your system I'd be sorry but please be aware I assume no responsibility
# or liability!
#
# -----------------------------------------------------------------------

import subprocess, csv, sys, socket

# Define a function to send magic packet to wakeup machine.
# Takes MAC address as input & will broadcast on default NIC

#def WOL(mac):
#    data = ''.join(['FF' * 6, mac.replace(':', '') * 16])
#    sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
#    sock.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
#    sock.sendto(data.decode("hex"), ("255.255.255.255",9))

def WOL(mac,pc):
    from datetime import datetime
    now = datetime.now()
    dt_string = now.strftime("%d/%m/%Y %H:%M:%S")
    f = open('/var/log/guac_wol.log','a')
    risultato = subprocess.Popen(['/usr/bin/sudo','-u','wol','ssh','IL_MIO_GATEWAY_1',mac],stdout=subprocess.PIPE,stderr=subprocess.PIPE)
    linerisultato = risultato.stdout.readline()
    f.write(dt_string + ' - ' + pc + ' - ' + linerisultato)
    risultato = subprocess.Popen(['/usr/bin/sudo','-u','wol','ssh','IL_MIO_GATEWAY_2',mac],stdout=subprocess.PIPE,stderr=subprocess.PIPE)
    linerisultato = risultato.stdout.readline()
    f.write(dt_string + ' - ' + pc + ' - ' + linerisultato)

# Open and tail Tomcat logfile. We can expect Guac connection
# data to be logged here. This includes the Guac username that connects
# out to another machine on the network, and the connection number from
# the connection list in Guac. This list appears to be numbered as the
# first being #2 (assume #1 is the logged in user that created the
# connection?).

logfile = subprocess.Popen(['tail','-F','/var/log/tomcat9/catalina.out'],stdout=subprocess.PIPE,stderr=subprocess.PIPE)

# Start reading the logile data line by line as it arrives.
# Open the macs.list file to get machine connection numbers and associated
# MAC addresses. Then continue to read logfile for Guac username and
# connection number. If a match is found between the logged connection
# number & id number from list file, call the WOL function to wakeup the
# machine via the associated MAC address (ad infinitum).
#
# Could also use the username instead of id number but some users may
# have multiple connections....

while True:
    line = logfile.stdout.readline()
    with open('/opt/localbin/macs.list') as inifile:
        reader = csv.DictReader(inifile)
        if 'connected to connection' in line:
            q1 = line.find("\"")
            q2 = line.find("\"",q1+1)
            q3 = line.find("\"",q2+1)
            q4 = line.find("\"",q3+1)
            user = line[q1+1:q2]
            conn_num = line[q3+1:q4]
            for row in reader:
                if(row['id']) == conn_num:
                    WOL(row['mac'],row['pc'])

Problemi dopo riavvio del server Guacamole legati al timezone (rilevato in fase di cambio fuso orario).

Dopo un riavvio del server l’applicativo Guacamole non riesce più ad accedere al database mysql/mariadb.

Il file log /var/log/tomcat9/catalina.out trovo il seguente messaggio d’errore

[2020-03-29 13:26:52] [info] 13:26:52.289 [http-nio-8080-exec-9] ERROR o.a.g.rest.RESTExceptionMapper - Unexpected internal error:
[2020-03-29 13:26:52] [info] ### Error querying database.  Cause: java.sql.SQLException: The server time zone value 'CEST' is unrecognized or represents more than one time zone. You must configure either the server or JDBC driver (via the 'serverTimezone' configuration property) to use a more specifc time zone value if you want to utilize time zone support.

Questo il contenuto del file /etc/timezone

Europe/Rome

Ho risolto il problema in questo modo (su segnalazione del buon Roberto Resoli che mi ha salvato da un bel casino !!):

– popolate alcune tabelle di mysql/mariadb

mysql_tzinfo_to_sql /usr/share/zoneinfo | mysql -u root -p mysql

– modificato il file /etc/mysql/mariadb.conf.d/50-server.cnf nel modo seguente

# This group is only read by MariaDB servers, not by MySQL.
# If you use the same .cnf file for MySQL and MariaDB,
# you can put MariaDB-only options here
[mariadb]
default_time_zone=Europe/Rome

– riavviato il servizio mariadb

service mariadb restart

Per approfondimenti:
https://dev.mysql.com/doc/refman/8.0/en/time-zone-support.html
https://mariadb.com/kb/en/time-zones/
WordPress Appliance - Powered by TurnKey Linux