Menu Chiudi

Pillola #65: Gestione telelavoro tramite Guacamole

Questa pillola è stata modificata per poterla usare su di una rete estesa, con più di mille PC suddivisi in più di 40 sottoreti.

La versione originale la trovate qui: “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/wol/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:

  • monitora il contenuto del file “/var/log/tomcat9/catalina.out”
  • cerca il messaggio di connessione dell’utente
  • ne estrae l’ID della connessione che l’utente vuole usare
  • si appoggia a due file:
    • macs.list: contiene
    • serversWOL.list
  • ne estrae il MAC del PC che l’utente vuole usare
  • la rete su cui si trova il giusto ServerWOL
  • avvia tramite ssh un comando sui ServerWOL per l’accensione del PC.

Lato ServerWOL

Il contenuto dello script richiamato sul server WOL, che si occupa di inviare il magic packet per il Wake On LAN dei client

# cat /opt/wol/AccensioneWOL.sh
#!/bin/bash

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

/usr/bin/sudo /usr/sbin/etherwake -D -i eth0 $1 
# Lancio WOL anche sulla VLAN 
/usr/bin/sudo /usr/sbin/etherwake -D -i eth0.12 $1 
echo "$(date +"%F %T") - Accensione PC $1" >> /var/log/guac_wol.log 
exit 0

Nello script vediamo il lancio anche sulla VLAN del pacchetto WOL, non conviene complicare il codice ulteriormente per gestire l’interfaccia aggiuntiva.

Tramite il file /opt/wol/macs.list vengono configurati i relativi MAC address connessi ai vari PC (connessioni in Guacamole). Esso contiene le triplette:

  • id: id della connessione derivato dal DB di Guacamole
  • mac: del PC corrispondente alla connessione
  • net: numero della rete su cui si trova il PC ed il relativo ServerWOL

Il file /opt/wol/rasps.list contiene invece le coppie:

  • net: le rete dove si trova il ServerWOL
  • raspb: l’IP del ServerWOL da contattare

Per consentire l’esecuzione del comando WOL sui vari gateway ho:

  • creato un nuovo utente wol su guacamole e su tutti i ServerWOL
  • 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 ServerWOL, vedi Pillola #70
  • 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/wol/guac_wol.py

[Service]
ExecStart=/opt/wol/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 /opt/wol/guac_wol.py
#!/usr/bin/env python3
#
# --------------------------Readme---------------------------------------
#
# JAN 2022-11-25
# Derived from the original Guacamole wake-on-lan (WOL) script.
# we thank: Luke P 26 Feb 2018
#           Marco Agostini 28 Feb 2019
#
# This is designed to run on the Guac host machine and will send a
# 'magic-packet' wakeup call to a specified raspberry machine on the same
# network of the desired PC 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' and a 'raspbs.list file in the same directory as it runs from.
# The MAC file must contain only the header detail, and comma-separated fields
# of id (Guac connection number), MAC addr (of thePC) and network (of the PC). 
# --- example macs.list --- #
# id,mac,net
# 1,11:22:33:44:55:66,11
# 2,22:33:44:55:66:77,12
# 3,33:44:55:66:77:88,2
# 4,44:55:66:77:88:99,44
# 5,55:66:77:88:99:00,13
# 6,66:77:88:99:00:aa,17
# etc,etc
# ----------------------------- #
#
# The second file, like the first, contain only header detail and
# a comma-separated fields of network (of the PC) and ip (of the remote raspberry).
# --- example raspbs.list --- #
# net,raspb
# 11,192.168.11.5
# 12,192.168.12.5
# ----------------------------- #
#
# 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/tomcat8/catalina.out
# You would probably need to change this path if your system
# uses tomcat9.
#

# This is a rough 'n ready script and has not been tested for any length
# of time. 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

def WOL(mac, net):
# imposto come default IP il raspberry del sistema informativo
ip = '192.168.11.6'
from datetime import datetime
now = datetime.now()
dt_string = now.strftime("%Y/%m/%d %H:%M:%S")
with open('/opt/wol/raspbs.list', newline='') as inifile:
raspb = csv.DictReader(inifile)
for riga in raspb:
if (riga['net']) == net:
ip = riga['raspb']
f = open('/var/log/guac_wol.log', 'a')
risultato = subprocess.Popen(['/usr/bin/sudo','-u','wol','ssh',ip,mac],stdout=subprocess.PIPE,stderr=subprocess.PIPE)
linerisultato = risultato.stdout.readline().decode("utf-8")
f.write(dt_string + ' - [MAC] ' + mac + ' - [NET] ' + net + ' - ' + linerisultato + '\n')
#Riga successiva solo per debug
#print(dt_string + ' - ' + mac + ' - ' + net + ' - ' + str(linerisultato) + '\n')

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

while True:
line = str(logfile.stdout.readline())
with open('/opt/wol/macs.list', newline='') 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:
#riga successiva solo per debug
#print('id:', row['id'], 'mac:', row['mac'], 'net:', row['net'])
WOL(row['mac'], row['net'])


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