TCP Wrappers è un software che permette il controllo degli accessi ai servizi di rete come Ftp, Ssh, Imap o Pop, offerti da un sistema unix-like. Esso ricorre ad alcune ACL (Access Control List) per filtrare le connessioni, registrare il nome dell'host che effettua la richiesta ed il particolare servizio richiesto. Generalmente lo trovate già installato di default e si appoggia al demone syslogd
per le operazioni di log.
Fu originariamente sviluppato da Wietse Zweitze Venema, fisico e programmatore dell'Eindhoven University of Technology, per controllare gli attacchi di un insistente cracker.
Apriamo una breve parentesi per dire che, in un sistema Unix, i processi possono essere avviati in due modalità: daemon mode (ovvero standalone) e super-daemon. Nella seconda ipotesi esiste un "super processo" che attende le connessioni ai servizi di rete ed una volta ricevuta la richiesta, attiva il processo corrispondente.
Con un demone standalone è necessario allocare immediatamente risorse di sistema (cpu, memoria e così via) per il suo funzionamento, al contrario il super demone le richiede solo in caso di effettiva necessità. Per contro vi sarà una riduzione delle prestazioni ed un allungamento dei tempi di risposta. L'amministratore di sistema dovrà dunque scegliere la modalità che meglio si adatta al singolo processo in base all'uso che ne verrà fatto ed alle sue caratteristiche di funzionamento. Ad esempio Apache è già ottimizzato per il risparmio di risorse, quindi normalmente non conviene ridurne le performance.
Il super server originario, ancora usato da molti Unix commerciali e da alcune distribuzioni Linux, è inetd; il super demone di nuova generazione, ormai adottato dalla maggior parte delle distribuzioni, è xinetd il quale fornisce ulteriori garanzie di sicurezza e flessibilità di configurazione.
L'idea del programmatore olandese fu questa: il super demone anziché richiamare direttamente il demone figlio, cede il controllo ad un processo intermedio (tcpd
) che opera le necessarie verifiche, esegue le attività di log e decide se avviare o no il processo richiesto.
Originariamente solo i servizi gestiti dal super server inetd
godevano di questo beneficio, attualmente molti demoni di rete sono compilati con la libreria libwrap
che fornisce le funzionalità descritte. Volendo potreste scrivere un vostro software di rete e compilarlo con tale libreria. Quando viene effettuato un tentativo di connessione ad un servizio "tcp wrapped", per prima cosa vengono controllati i file contenenti le ACL per determinare se il client sia autorizzato o meno.
Potete utilizzare il comando strings
per verificare l'esistenza del supporto ai TCP Wrappers. Nel caso del servizio Ftp gestito dal demone vsftpd
:
# strings /usr/sbin/vsftpd | grep libwrap libwrap.so.0
La risposta del sistema, riportata nella seconda riga, ci conforta in proposito. Se invece ci venisse restituito solo il prompt dei comandi saremmo sfortunati.
I file di configurazione delle ACL
Il controllo sui servizi che utilizzano TCP wrappers viene affidato a due file: hosts.allow
ed hosts.deny
normalmente presenti nella directory /etc
. I nomi sono abbastanza espliciti: il primo elencherà gli host ai quali è consentito l'accesso, mentre il secondo quelli a cui è negato.
I file vengono analizzati in ordine, prima hosts.allow
, il quale ha la precedenza rispetto alle regole specificate in hosts.deny
. La consultazione dei file termina alla prima corrispondenza trovata, quindi l'ordine con cui compaiono le regole è importante. Attenzione: se non vengono trovate corrispondenze tra servizio richiesto e host richiedente l'accesso viene consentito.
In altri termini il flusso prevede l'analisi dell'hosts.allow
, se viene trovata un'entry il servizio viene erogato altrimenti si passa ad analizzare l'hosts.deny
, se viene trovata un'entry il servizio viene negato altrimenti viene comunque concesso.
I file sono tipici file di configurazione testuali secondo lo stile Unix: le regole andranno inserite una per riga, le righe vuote o che iniziano con il carattere #
, verranno ignorate. La sintassi ha la seguente forma:
elenco_demoni : elenco_clients [: comando_shell]
- elenco_demoni: elenco di uno o più nomi di servizi separati da spazi (si possono usare delle wildcard);
- elenco_clients: elenco di uno o più nomi di host o numeri IP separati da spazi (si possono usare delle wildcard);
- comando_shell: opzionale, se specificato verrà eseguito al matching della regola.
Ad esempio se inseriamo in hosts.allow
la regola:
sshd : 192.168.1.10
specifichiamo di voler concedere l'accesso ssh al numero IP 192.168.1.10. Al contrario se inserita in hosts.deny
, indica che vogliamo impedire l'accesso ssh a quell'IP. Ricordo però l'uso combinato dei due file da cui dipenderà il risultato finale, come si capirà meglio dagli esempi successivi.
È importante notare che le modifiche apportate ai file di configurazione hanno effetto immediato senza dover riavviare i servizi di rete.
Si è accennato alla possibilità di usare delle wildcard all'interno delle regole, eccone l'elenco con il loro significato:
- ALL: qualunque daemon o qualunque client;
- LOCAL: vera per gli host il cui nome non contiene un punto '.' ovvero vera per il dominio locale;
- UNKNOWN: ogni nome di host o indirizzo di host o client sconosciuti (attenzione se il servizio dns non funziona la regola risulta sempre vera);
- KNOWN: l'opposto della precedente;
- PARANOID: vera per tutti gli host in cui l'hostname non verifica l'host address.
Infine va menzionato l'operatore EXCEPT
che, se usato all'interno di una regola, introduce un'eccezione alla regola stessa.
Esempi di configurazione
Vediamo ora alcuni esempi che chiariscono la teoria e possono fornire uno spunto per la personalizzazione delle configurazioni.
Per ottenere un host senza alcuna protezione possiamo specificare in hosts.allow
:
ALL : ALL
e lasciare vuoto hosts.deny
. In questo caso il primo ALL indica tutti i servizi, mentre il secondo qualunque client. Poiché in hosts.deny
non neghiamo l'accesso ad alcuno non poniamo vincoli di sorta!
Al contrario, lasciando vuoto hosts.allow
ed inserendo la medesima regola in hosts.deny
, otteniamo di negare qualunque servizio a qualunque client.
Un possibile approccio alla configurazione consiste nel consentire l'accesso a determinati servizi solo a specifici host. Per ottenere ciò inseriamo la regola ALL : ALL
in hosts.deny
e poi dedichiamoci alla compilazione delle ACL in hosts.allow
.
#tutti possono accedere via ssh ad #eccezione dell'host con l'ip specificato sshd : ALL EXCEPT 192.168.0.15 #tutti gli host del dominio .miodominio.it possono #fare ftp ad es. host1.miodominio.it host2.miodominio.it vsftpd : .miodominio.it #il servizio imap risulta accessibile #solo agli ip specificati imapd : 10.0.0.12 10.0.0.18 192.168.1.34 #tutti gli host del local domain sono #autorizzati eccetto l'utente ermanno #da qualunque macchina ci provi sendmail : LOCAL EXCEPT ermanno@* #tutti i client con indirizzo ip #192.168.0.x possono usare il servizio pop3 ipop3d : 192.168.0.
I commenti riportati dovrebbero essere sufficienti a spiegare il significato delle regole. Oltre alle wildcard si sono utilizzati dei "pattern" come la stringa che inizia con '.
' per individuare un gruppo di hostname in '.miodominio.it'. Analogamente il '.
' finale serve ad individuare un gruppo di numeri IP in '192.168.0.'. Una stringa 'n.n.n.n/m.m.m.m' simile a 133.155.45.0/255.255.254.0
verrebbe interpretata come coppia rete/maschera di rete. Infine la regola relativa a sendmail mostra anche l'utilizzo del carattere '*
' con il consueto significato cui si può affiancare '?
'.
In alternativa si potrebbe seguire la via di concedere l'accesso ai sevizi di rete a tutti i client, ponendo delle restrizioni solo a particolari host. In tal caso lasciamo vuoto hosts.allow
ed inseriamo i blocchi in hosts.deny
.
in.telnetd : 10.0.0.12
Così facendo neghiamo il servizio Telnet al solo host 10.0.0.12
. Personalmente preferisco, se possibile, il primo approccio. Risulta inoltre consigliato utilizzare numeri IP al posto di nomi di host o nomi di dominio risultando più "sicuri" e non dipendenti dal servizio DNS.
I comandi di shell
Abbiamo visto come la sintassi delle ACL preveda un terzo argomento, opzionale, che abbiamo identificato genericamente come comando di shell. La regola che segue, se inserita in hosts.deny
, nega l'accesso Ssh all'ip 10.0.0.2, ma nel contempo registra alcune informazioni nel file /var/log/mio.log
.
sshd : 10.0.0.2 : spawn (/bin/echo `date` %u %a >> /var/log/mio.log) &
Nell'esempio compaiono le cosiddette "espansioni" %u
e %a
. La prima verrà sostituita con il nome dell'utente (se determinabile), mentre la seconda con l'host di provenienza. Si noti l'uso degli apici gravi (`
) per stampare il valore del comando date anziché la stringa "date". Il carattere '&
' finale indica semplicemente di non attendere il completamento del comando (background processing).
Ora, invece, in hosts.allow
non poniamo vincoli all'accesso via Ssh, ma inviamo una comunicazione a root quando viene richiesta la connessione.
sshd : ALL : spawn (/bin/mail -s "%u da %a cerca di accedere" root) &
Mediante il programma mail
viene inviata una email all'utente root nel cui soggetto (-s
) compaiono le informazioni richieste.
La sintassi usata negli esempi può essere arricchita grazie ad un'estensione del linguaggio delle ACL. Essa permette di utilizzare l'ultimo campo in modo più potente e flessibile, non limitandosi ad un comando di shell, ma specificando diverse opzioni una di seguito all'altra.
È possibile ad esempio indicare il livello di log desiderato (facility) o eseguire in modo diverso i comandi (spawn e twist) ed altro ancora. Lo spazio a disposizione non permette di approfondire l'argomento consiglio a tutti la lettura delle pagine di manuale relative a hosts_access
per il linguaggio di controllo di default e hosts_options
per la citata estensione. Basterà digitare al prompt dei comandi:
# man 5 hosts_access # man hosts_options
Qui troverete, inoltre, l'elenco di tutte le possibili "espansioni".
Una breve nota: ricordatevi che l'ultima riga dei file delle ACL deve contenere un carattere di newline, altrimenti l'ultima regola probabilmente non verrà eseguita con conseguenze immaginabili. In tal caso, ad esempio in /var/log/messages
, potreste trovare un messaggio simile a questo:
Jan 2 13:30:43 ermanno vsftpd[25634]: warning: /etc/hosts.deny
, line 8: missing newline or line too long
Conclusioni
In queste pagine abbiamo descritto le basi del meccanismo TCP wrappers e gli esempi forniti dovrebbero risultare sufficienti per le comuni configurazioni. La documentazione ufficiale potrà fornirvi ulteriori spunti per regole d'accesso più sofisticate.
Gli utenti legittimi non noteranno alcuna differenza nelle consuete operazioni, mentre eventuali intrusi non riceveranno alcuna informazione sul perché la loro connessione sia fallita. Inoltre, operando in maniera "separata" dai servizi che protegge, consente di gestirli globalmente attraverso un set di regole condivise.
La sua popolarità è senza dubbio riconducibile alla facilità e rapidità di configurazione, ma andrebbe sempre affiancato a più robusti, anche se complessi, sistemi di protezione (come iptables).