La posta elettronica è indubbiamente uno di servizi
telematici più usati da ogni sorta di utenza. Purtroppo è anche
il punto più critico circa la sicurezza delle informazioni che trasporta,
per il semplice fatto che normalmente tra il computer client (cioè quello
che chiama) ed il server (quello che risponde) i dati transitano in chiaro.
Nel gergo informatico "in chiaro" significa semplicemente "non criptato", e
questo implica che chiunque si trovi sulla nostra stessa rete può facilmente
ricostruire le nostre conversazioni. A parte il fatto che probabilmente nessuno
di noi usa la posta elettronica per gestire una guerra fredda, direi che è
molto fastidiosa la consapevolezza che la nostra privacy può essere violata
assai facilmente.
Quando ci si rese conto di quanto insicure fossero le comunicazioni via Internet,
con i ben noti fenomeni di hackeraggio dei numeri delle carte di credito usate
per fare del commercio elettronico, si corse ai ripari introducendo appositi
"protocolli sicuri", ovvero criptati. I più noti sono SSH (Secure SHell)
ed SSL (Secur Soket Layer) ideato da Netscape e successivamente modificato negli
anni per renderlo sempre più sicuro.
In questo articolo vorrei spiegare come ho realizzato un server di posta in
grado di accettare connessioni sicure basandosi sull'openSSL, la versione free
di SSL. Prima di descrivere i dettagli tecnici tenterò di gettare qualche
minima base teorica su come i computer dialogano tra loro usando i protocolli
di internet (TCP/IP); per gli esperti questa parte è superflua, ma credo
che molti novizi siano interessati a capire almeno in linea di massima cosa
accade quando il loro PC si affaccia sulla rete di Internet!
A tutti buona lettura.
Esistono molti modi per far parlare tra loro due o più
computer, ma qui siamo interessati alla comunicazione su grande scala che è
Internet.
Per iniziare diciamo che nel momento in cui un calcolatore si immette in rete,
esso deve essere individuato univocamente in tutto il mondo da una sorta di
"targa" che in linguaggio più tecnico si chiama "numero IP", dove IP
sta per Internet Protocol. Una volta stabilita l'univocità del computer,
alcune macchine particolari che fungono da "corrieri" provvedono ad indirizzare
i dati (suddivisi in piccoli pacchetti) al computer che deve riceverli; tali
"corrieri" sono i "router". Detto in termini molto semplici, quando un programma
vuole inviare un'informazione tramite rete, il kernel (cioè il cuore
del Sistema Operativo) provvede a spezzettarla in tanti piccoli pacchetti, ognuno
dei quali contiene un "intestazione" ed un "corpo": l'intestazione contiene
i dati del mittente e del destinatario del pacchetto, oltre al preavviso di
quanto sarà lungo il corpo dello stesso, cioè la parte di dati
trasportata dal pacchetto in questione.

Schema (elementarissimo!) di comunicazione tra computer. Figura presa da
"Linux, TCP/IP e le reti" di M. Daddi
Ogni pacchetto viene numerato, e l'informazione viene ricostruita
dal destinatario man mano che i pacchetti (inviati a lui dal router) gli arrivano.
Se ad un certo punto il kernel del ricevente vede che manca il pacchetto n°16,
lo dice al router e questo lo fa a sua volta presente al mittente: "Huè,
qui ci siamo persi un po' di roba, rimanda il pacchetto 16 e, per sicurezza,
i due prima ed i due dopo". Il motivo per cui a volte la rete ci sembra lenta
è proprio questo, cioè l'eccessiva frammentazione dei pacchetti
a causa dell'alto traffico nei nodi Internet!
Oltre al fatto della suddivisione in pacchetti, c'è un'altra cosa che
non posso esimermi dallo spiegare, anche solo sommariamente: si tratta del concetto
di "porta", che alcune volte chiamerò (erroneamente!) "socket". Dunque,
è evidente a tutti che noi, quando siamo in rete, usiamo una singola
linea (un "filo", tanto per intenderci!) per fare più cose, ad esempio
per la posta, per navigare con Netscape, per fare telnet, per le chat e chi
più ne ha più ne metta. La domanda che uno si porre è:
come fa il mio computer a capire a quale applicazione deve andare un pacchetto
IP? Cioè, ammettiamo che io scarichi la posta e nel frattempo navighi
in Internet; ebbene, sulla connessione di rete passeranno più pacchetti,
tutti destinati al mio IP, ma poi chi dice ad un pacchetto di andare a Netscape
e ad un altro di andare a kMail?!? È ovvio che ci deve essere una qualche
organizzazione più fine dietro tutta la bella interfaccina grafica dei
programmi... allora coraggio, vediamo di capirci qualcosa: non è per
questo che usiamo Linux? ;-)
L'arcano si spiega "abbastanza" facilmente. Il kernel (sì, sempre lui!)
suddivide la connessione di rete in molte parti, come se da un filo ne diramasse
molti altri (tanti, si tratta di migliaia!), e su ogni filo mettesse in ascolto
un guardiano che non controlla altro se non quello che gli spetta. In termini
più tecnici possiamo dire che una singola interfaccia di rete viene suddivisa
in più "porte", ognuna specializzata per ascoltare un determinato tipo
di "protocollo". Eh già, perché una connessione Internet sfrutta
più protocolli (infatti si parla della "famiglia di protocolli" TCP/IP),
ad esempio l'SMTP per spedire la posta, il POP/IMAP per ritirarla e così
via.

NMAP è un'utilità che permette di vedere quali sono le porte
aperte su un server.
Quando arriva il primo pacchetto di dati, diciamo di una mail, il kernel va a leggere qual'è il protocollo usato, vede SMTP, sa che il guardiano ("daemon", come si è solito chiamarlo) per l'SMTP si deve trovare sulla porta numero 25 e quindi controlla che effettivamente questo sia "sveglio", cioé pronto a stabilire la connessione; all'occorrenza lo sveglia piuttosto bruscamente con un secco "Ragazzo, qui c'è un pacchetto per te", il poverino non ha neppure il tempo di capire cosa sta succedendo ed ecco il secondo, il terzo e via di seguito tutti i dati che arrivano in fila indiana. Se invece il computer non deve essere in grado di usare l'SMTP, l'amministratore avrà disabilitato quella porta (la 25) e non ci sarà nessuno pronto ad utilizzare i pacchetti: questi saranno rimandati indietro con un poco diplomatico "Connection refused by the server", o qualcosa di analogo. Ecco, tra l'altro, perché è importante chiudere tutte le porte che non si debbono usare: esattamente ciò che non fa Windows!

Un client viene allertato circa la sua "incapacità di connettersi"
al server flypro.roma2.infn.it, il cui numero IP è 141.108.16.119
Riguardo tali porte posso aggiungere che non tutte sono "libere", cioè ne esiste una serie che di default svolgono un certo lavoro, come ad esempio si può leggere dal seguente stralcio del file di configurazione dei servizi:
ftp 21/tcp
ssh 22/tcp
# SSH Remote Login Protocol
telnet 23/tcp
# 24 - private
smtp 25/tcp mail
nameserver 42/tcp
name # IEN 116
gopher
70/udp
finger
79/tcp
www
80/tcp http
# WorldWideWeb HTTP
imap
143/tcp
# Interactive Mail Access
si vede, ad esempio, come l'smtp viene assegnato alla porta
25, il telnet "classico" alla porta 23 e così via. Tuttavia moltissime
porte (circa 30 mila!) rimangono libere e disponibili per gli utenti, oltre
che per gli hacker!
Proprio l'esistenza di queste porte libere permette di creare nuovi servizi
basandosi su quelli già esistenti. Tra poco verrà fornito un esempio
che reputo molto utile e che riguarda la posta elettronica... A fine di questo
"paragrafo" mi scuso con gli esperti: so perfettamente che stanno rabbrividendo
per come ho esposto questi semplici cenni circa la comunicazione tra computer
che, ribadisco, non hanno nessuna pretesa di completezza e formalità.
Riepiloghiamo.
Finora abbiamo visto che la comunicazione via Internet è generalmente
insicura a causa dell'assenza di crittografia, tuttavia nel tempo sono stati
ideati algoritmi e protocolli per la trasmissione sicura (SSH ed SSL, ad esempio).
I vari protocolli, che formano la famiglia TCP/IP, vengono riconosciuti dal
kernel che dipendentemente dalla loro natura li indirizza sulla porta a loro
dedicata oppure li rimanda indietro se questa non è disponibile. Le porte
dei servizi comuni sono state standardizzate, ma ne rimane un gran numero per
creare socket ad-hoc, cioè per creare servizi nuovi o non previsti. Inoltre
nessuno ci vieta di spostare un servizio da una porta all'altra, ad esempio
se vogliamo far parlare due calcolatori tramite ssh sulla porta 12419 (anziché
sulla 23 che è quella standard) possiamo farlo semplicemente modificando
il file services su entrambi i computer, semprechè questi non abbiano
la porta 12419 già impegnata da altri servizi: mica vogliamo fare un'ammucchiata
di demoni dentro una porta!... il kernel è molto pudico e non lo permetterebbe
;-)
Veniamo ora al motivo vero e proprio del presente articolo. Esistono vari modi
per ritirare la posta da un server. I più comuni sono il POP3 e l'IMAP.
La differenza sostanziale tra i due è che il POP3 lavora più "in
locale" mentre l'IMAP lavora più "sul server"; in altre parole con il
POP3 ci si collega, si ritira la posta, la si cancella dal server, ci si disconnette
e si lavora a casuccia sul proprio PC mentre sul server non rimane più
traccia di noi. Invece con l'IMAP lasciamo sempre copie aggiornate delle nostre
mail, e questo può essere utile se vogliamo disporre della nostra posta
in tutte le parti del mondo oppure se vogliamo "sfruttare" i continui backup
solitamente effettuati sui server.
Supponiamo di voler usare l'IMAP, altrimenti dovreste attendere l'uscita dell'articolo
"SSH tunneling over POP3", fate un po' voi!
Come noto (dal pezzetto di "services" riportato sopra) la porta del demone per
l'IMAP3 è la 143. Questo significa che quando noi chiediamo al server
di darci la posta, mandiamo dei pacchetti alla porta 143. La prima cosa che
il server ci chiede è ovviamente il nome di login, quindi la password
e se tutto va bene ci lascia entrare. Il punto critico è che login/password
passano in chiaro, quindi chiunque le può leggere.

In questa sessione telnet si vede chiaramente come avviene la transazione
tra server e client
Ma non finisce qui: anche la posta transiterà in chiaro!
È a dir poco ovvio che così facendo non può esserci potenzialmente
nessuna pretesa di riservatezza. Personalmente la cosa mi infastidisce parecchio
perché, tanto per dirne una, se mia sorella diventasse un hacker potrebbe
leggere tutte le tenerissime (ed imbarazzantissime) lettere d'amore che mi sono
scambiato con la mia meravigliosa ex, Roberta, e la cosa non mi farebbe piacere
in quanto non potrei più ricattarla come faccio ora visto che sono io
il "root" del sistema!
A parte le battute, qualcuno potrebbe avere motivi più seri per evitare
di essere "sniffato", ad esempio può mandare dati molto personali via
mail, progetti, risultati di analisi o di esperimenti. La domanda che sorge
quindi spontanea è: si può fare in modo che i dati di login e
tutto il resto passino in maniera comprensibile solo dal server e dal mio PC?
La risposta è affermativa: è possibile crittografare tutti i dati
in transito su una connessione IMAP con un livello di complicatezza alto quasi
a piacere, ed il trucco consiste nello sfruttare l'SSL. Il concetto è
piuttosto semplice, e di questa semplicità bisogna ringraziare il kernel
di Linux e tutti gli sviluppatori che ci lavorano!
Dunque, come primo passo si chiude la porta 143. Caspita, si dirà, così
sì che è sicuro: non posso più fare la connessione! Ma
quello che si fa è di aprire un'altra porta sulla quale metteremo in
ascolto IMAPD (il demone di IMAP, si noti che finisce con la D di Daemon!) però
"incapsulato" in qualche modo dentro la guaina dell'SSL che usa è un
protocollo crittografato. In pratica si realizza un "tunnel" di SSL intorno
al demone dell'IMAP, quindi tutto ciò che passa da/verso quest'ultimo
rimane costantemente sotto il controllo dell'inviolabile SSL. Qualcuno obbietterà
"perché inviolabile?". In informatica "inviolabile" sta per "raramente
indovinabile", e a conti fatti sembra che per trovare la chiave di crittografia
dell'SSL attuale occorra un tempo molto maggiore dell'età dell'Universo!
Se anche così vi sentite insicuri, scrivete le vostre lettere a mano
con inchiostro simpatico e consegnatele di persona...
Vorrei far notare che la tecnica del tunneling è più generale
di quanto non emerga dalle mie poche parole. Si può fare il tunneling
del POP3, dell'FTP ed addirittura di sessioni grafiche tramite SSH. È
palese, tuttavia, che le connessioni "tunnel" saranno più lente di quelle
standard, se non altro perché le macchine devono criptare e decriptare
in real-time tutti i dati in transito. Nel mio caso ho un Pentium 133 che funge
da server (di tutto!) ed avendo scelto inizialmente un eccessivo livello di
crittografia alla terza connessione il processore "crepava" e con lui tutta
la rete! Insomma, quello che voglio dirvi e di non esagerare altrimenti dovreste
avere un server Alpha quadriprocessore per lavorare!
Nelle prossime righe vorrei brevemente dire come funziona OpenSSL,
per poi passare al conclusivo paragrafo circa i dettagli tecnici necessari per
settare il server IMAP sicuro. Il punto chiave sta nella presenza di due certificati
(o "firme" elettroniche) che permettono il riconoscimento reciproco e fidato
di due computer in rete.
Anzitutto l'amministratore del server provvederà a generare due "chiavi",
una detta "pubblica" ed una detta "privata". Ad un certo momento accade che
un client invia una richiesta di connessione al server e che questo, in risposta,
esibisca la sua chiave pubblica. L'utente del client viene dunque avvertito
della richiesta di stabilire una connessione crittografata ed inizia la visualizzazione
dei suoi dati caratteristici e tante altre amene cosine che qui tralascio!
Supponiamo che io (ovvero il client) decida di accettare la connessione criptata:
a mia volta genererò (via la chiave pubblica del server) una chiave che
sarà mantenuta localmente. Manderò la mia chiave al server e questo
la decripterà grazie alla presenza della sua chiave privata!
Forse sembra il gioco delle matrioske, ma l'argomento è astuto: la chiave
privata del server è super-sicura ed è essenziale per decriptare
il certificato spedito dal client, a sua volta generato basandosi sulle informazioni
contenute nella chiave pubblica del server. Questo significa che ogni client
può generare un proprio certificato, ma solo il server può dire
da quale client questo proviene!... Spero di non aver contribuito ad aumentare
la confusione che di solito abbonda nella questione delle chiavi di crittografia
;-)
Un'ultima cosa: i certificati possono essere generati "privatamente" solo se
non si usa il server per scopi di commercio elettronico ufficiale: in tal caso
occorre rivolgersi ad enti appositi.
Bene, a questo punto siamo padroni del TCP/IP e dei protocolli
crottografati (?), quindi non ci resta che operare!
Anzitutto bisogna andare in giro per la rete a raccattare i vari pezzi che ci
servono nel formato adatto alla distribuzione che usiamo. Siccome non è
mia intenzione stare a descrivere come installare tutto il necessario su ogni
versione di Linux, mi limiterò a quelle che uso io (Linux Mandrake 6.1
e 7.0, nonché RedHat 6.x) in quanto le differenze si riscontrerebbero
solo nella "preparazione" del sistema: prendere i sorgenti, ./configure, make,
make install... insomma lo trovate scritto in tutti "readme" di tutti i
pacchetti.
Dunque, lasciando che qualcuno storca il naso, io non ho compilato nulla perché
mi sono scaricato i meravigliosi RPM che mi servivano e tutto ha funzionato
senza lacrime.
Gli ingredienti per continuare sono:
openssl (io
uso la versione 0.9.4)
openssl-devel
(io uso la versione 0.9.4)
imap (io
uso la versione 4.7 della W.U.)
stunnel
(io uso la versione 3.3)
I pacchetti, in formato RPM, possono essere scaricati da qualsiasi mirror della Mandrake, su rpmfind.net o su SuperAlberT.it ftp://ftp.SuperAlberT.it/pub/Apps/, e poi installati col solito "rpm -U nome_pacchetto". Ora veniamo al dunque, in pochi e semplici passi... Dopo il login (come root, ovviamente!) portiamoci nella directory /etc e modifichiamo i file di configurazione services ed inetd.conf come segue:
Nel file services aggiungiamo le righe
#
SSL tunneling over IMAP
simap 993/tcp
Nel file inetd.conf aggiungiamo le righe
#
SSL tunneling over IMAP
simap stream tcp nowait root /usr/sbin/stunnel stunnel -p /usr/local/ssl/certs/imapd.pem
-l /usr/sbin/imapd imapd
Commentiamo quello che abbiamo fatto.
Nel file services noi stabiliamo una corrispondenza (univoca!) tra
il numero di ciascuna porta ed il demone che dovrà sorvegliarla.
Il mio consiglio, pertanto, è di verificare preventivamente che
non ci siano altre righe in cui si assegna qualcosa alla porta 993! In
particolare, si noti che i numeri di porta nel file services non sono (in
generale) ordinati in ordine crescente, sicché conviene usare la
funzione "find 993" comunemente posseduta da tutti gli editor, oppure il
più linuxiano "grep 993 /etc/services".
Il secondo file, inetd.conf, è un pochino più complicato
ed ogni sua riga presenta varie opzioni; in generale la sintassi di ogni
riga è:
service socket-type protocol flag user server-path server-args
dove "service" è il nome del servizio, "socket-type"
è il tipo di socket (può essere stream o dgram per il TCP o l'UDP
rispettivamente), "protocol" è il tipo di protocollo, "flag" indica se
il server dovrà liberare la porta per consentire una nuova connessione
(nowait) oppure se il servizio non sarà disponibile finché il
server non avrà terminato la prima connessione (wait). Il campo "user"
indica qual'è l'utente proprietario del server che sarà attivato.
Infine "server-path" e "server-args" specificano la locazione del server e quale
argomenti gli si vogliono passare nel momento in cui viene lanciato.
La riga non commentata aggiunta al file inetd.conf dunque definisce
che il server "imaps", definito sulla famiglia TCP, viene avviato con i
permessi dell'utente root e deve essere presente un nuovo demone ad aspettare
connessioni sulla porta non appena il primo demone inizia il suo lavoro
(cioé non accade che, se un utente arriva per secondo a leggere
la sua posta, allora deve aspettare che il primo finisca i suoi comodi!).
Infine la lunga espressione "/usr/sbin/stunnel stunnel -p /usr/local/ssl/certs/imapd.pem
-l /usr/sbin/imapd imapd" sta a dire che il "vero" server è stunnel
e si prende carico di /usr/sbin/imapd lanciato semplicemente, senza alcuna
opzione aggiuntiva. La dicitura "-p /usr/local/ssl/certs/imad.pem" indica
ad stunnel dove si trova il pemfile-certificate, nel nostro caso imapd.pem
che ci accingiamo a generare.
Eh già, a questo punto non ci resta che creare il certificato
da esibile al client non appena questo si collega! Per farlo spostiamoci
nella directory /usr/local/ssl/certs/ e diamo il comando
openssl req -new -x509 -nodes -out imapd.pem -keyout imapd.pem
-days 999

Durante la generazione del certificato saranno poste alcune domande. Attenzione
in particolare a quella circa il "Common Name"
Il sistema ci presenterà delle domande, peraltro non particolarmente imbarazzanti, alle quali possiamo rispondere un po' come vogliamo purché, è fondamentale, nel campo relativo al "common name" si inserisca il nome esatto del server (del tipo www.nome.server.it) e non una cosa qualsiasi: poi nessuno pianga se non funziona niente!
Nulla di più facile: aprite una sessione di Netscape, andate su "Preferenze", "Mail server" e definite il server che avete appena creato di tipo "IMAP"; nella sottosezione relativa alle proprietà della connessione bisogna selezionare "Use Secure Connection"; salvate e... coraggio: ritirate la posta.

È fondamentale ricordarsi di "costringere" il client ad utilizzare
una connessione sicura!
Se tutto va come deve (?) verrete avvertiti della richiesta di connessione crittografata e vi verrà chiesto esplicitamente se volete continuare. Se dite di sì il famoso lucchetto in basso a sinistra sulla barra di Netscape passerà da aperto a chiuso: se lo cliccate potrete visualizzare tutti i dettagli del server sicuro che avete appena creato.

Se il nostro lavoro è stato eseguito correttamente, alla prima connessione
il browser ce ne renderà merito ;-)
Ora è ragionevole aspettarsi che nessuno, oltre il legittimo destinatario,
potrà leggere la posta!