Creare chiave e certificato per la criptazione TLS

TLS
Se ignorate cosa sia “TLS“: è il successore di SSL ma usa lo stesso principio.

Internet è la miglior invenzione dopo la pizza ma oggi più che mai è diventato un posto pericoloso. Dobbiamo affrontare script kiddie, servizi segreti fuori controllo e crimine organizzato su larga scala. E’ assolutamente fuori questione pensare di fornire un servizio su internet non criptato. Considero immediatamente compromessa una password che viaggia in chiaro su internet. Quindi dobbiamo creare una chiave ed un certificato crittografici per Postfix (SMTP), Dovecot (IMAP/POP3) e Roundcube (HTTPS).

Si potrebbe obbiettare che usare una connessione criptata tra il computer di un utente e il server di posta è inutile. Dopotutto la mail è inoltrata ad altri server di posta in chiaro. Anche se può essere vero per qualche server di posta, la maggior parte degli amministratori si sforzano di abilitare TLS anche per le comunicazioni server-to-server. Non ci si può fare troppo affidamento per la corrispondenza riservata ma è meglio che niente.

Curiosità
Non molto tempo fa un paio di provider di posta tedeschi fondarono l’alleanza “email made in Germany”: Indovinate cosa hanno fatto per rendere il modo un posto migliore… hanno abilitato TLS. 🙂
Precisazione
Non usate certificati differenti per Postfix e Dovecot. Il client mail di MacOS, per lo meno, rifiuterà la connessione con un messaggio di errore poco chiaro.

Perché indurre i client mail a fidarsi di un certificato?

Così come con il vostro browser web preferito, c’è una lista di autorità di certificati “fidate” nel mondo. Si, il vostro browser si fida di aziende che voi non avete neanche mai sentito parlare. E così fa il vostro client mail. Decadi fa le aziende riuscirono a convincere gli sviluppatori di browser a far in modo che i loro browser si fidassero di tutti i certificati firmati crittograficamente da loro. Questi certificati erano tecnicamente uguali ai certificati firmati localmente. Avevano semplicemente una firma creata da un computer di una tal azienda. Il più delle volte non c’era nemmeno un umano a controllare le richieste di firma. Considero l’odierno sistema di certificazione bacato.

Solo alcune aziende di certificati di cui il vostro browser si fida di default. E voi?

Nel precedente tutorial per Debian Jessie ho fatto una lunga comparazione di certificati firmati localmente, aziende PKI, LetsEncrypt e certificati a pagamento. Semplifichiamo le cose – useremo LetsEncrypt. Non c’è ragione di dare ancora soldi alla mafia dei certificati. Perché la considero una mafia? Perché è semplicemente sbagliato dare soldi in cambio di fiducia. E la recente storia di fallimenti imbarazzanti ci insegna che non si meritano alcuna fiducia. Anche la mia cara vecchia autorità di certificati preferita StartSSL (fornivano certificati gratuitamente) ha fallito così miseramente che tutti i maggiori broswer adesso considerano i loro certificati inaffidabili. Di recente hanno addirittura chiuso bottega.

LetsEncrypt è un progetto no-profit guidato da un ente californiano chiamato ISRG (Internet Security Research Group). Sono riusciti a mettere in piedi un’infrastruttura che finalmente permette a tutto il mondo di ottenere gratuitamente certificati fidati. Oggigiorno i loro certificati sono ritenuti fidati dalla maggior parte dei browser web e altri software – come client mail. Se il vostro boss ve lo chiede… i loro certificati sono tecnicamente sicuri quanto quelli firmati localmente. E no, non c’è alcun motivo di pagare ancora per un certificato. Perché alcuni lo fanno ancora? Probabilmente perché sono vittime di marketing e FUD.

Il certificato verrà usato in tre programmi:

  1. Roundcube (webmail fornita da Apache)
  2. Postfix (per l’autenticazione nella comunicazione SMTP con i vostri utenti)
  3. Dovecot (per l’autenticazione nella comunicazione IMAP)

Preparare il server web Apache per l’HTTP

Cominciamo con Apache. Il vostro server può servire più di un host virtuale basato sui nomi. Questo significa semplicemente che il vostro server web distingue quale file spedire al client in base al nome host usato nell’URL. Supponiamo di voler offrire il nome host webmail.example.org ai nostri utenti. Ovviamente il vostro server avrà un altro nome nel dominio che controllate. Userò questo esempio per tutto il tutorial e lo scriverò in grassetto per ricordarvi che dovete usare il vostro nome host.

Per prima cosa abbiamo bisogno di una directory radice per questo host:

mkdir /var/www/webmail.example.org

Ora dobbiamo creare un file di configurazione per l’host virtuale. Apache su Debian usa un sistema pulito per gestire gli host virtuali:

  • /etc/apache2/sites-available/*.conf contiene due file di configurazione di default. “000-default.conf” è un host virtuale HTTP e “default-ssl.conf” è un host virtuale HTTPS. Potete creare file arbitrari qui. Apache non li considererà automaticamente.
  • /etc/apache2/sites-enabled/*.conf contiene link simbolici (“symlinks”) che puntano ai file di configurazione della cartella /etc/apache2/sites-available. Solo i link *.conf in questa cartella verranno caricati da Apache.

Questo sistema permette di abilitare e disabilitare gli host virtuali senza dover eliminare alcun file di configurazione. Debian fornisce i comandi “a2ensite” (che sta per “apache2 enable site”) e “a2dissite”. Oltre a dei controlli di integrità, questi comandi essenzialmente creano e rimuovono symlink tra “sites-available” e “sites-enabled”.

Nota
I file di configurazione devono avere un suffisso “.conf” altrimenti vengono ignorati.

Potete rimuovere i symlink di default in /etc/apache2/sites-enabled/* a meno che non li usate già.

Create il nuovo file di configurazione per host virtuali /etc/apache2/sites-available/webmail.example.org-http.conf ed inserite:

ServerName webmail.example.org
DocumentRoot /var/www/webmail.example.org

Questa semplice configurazione permette ad Apache di gestire le richieste HTTP (sulla porta TCP 80 standard) se una certa linea nella richiesta del browser indica “Host: webmail.example.org”. Il browser quindi dice al vostro server web Apache quale nome server sta cercando. Questo permette di avere siti web multipli su un singolo indirizzo IP. (Tra l’altro questo funziona anche con HTTPS grazie a Server Name Indication.)

Abilitiamo il sito:

a2ensite webmail.example.org-http

Ci verrà detto:

To activate the new configuration, you need to run:
 systemctl reload apache2

Facciamolo.

Controlliamo se la configurazione funziona. Mettiamo un file di test nella cartella web radice:

echo "Just a test" > /var/www/webmail.example.org/test

Ora se apriamo l’URL http://webmail.example.org/test nel browser dovremmo vedere la scritta “Just a test”.

Questo è sufficiente per permettere a LetsEncrypt di creare un certificato per noi.

Ottenere un certificato LetsEncrypt

Debian Stretch ha già lo strumento più comune per gestire i certificati LetsEncrypt – certbot. Installiamolo:

apt install certbot

Per ottenere un certificato per il nostro dominio lanciamo:

certbot certonly --webroot --webroot-path /var/www/webmail.example.org -d webmail.example.com

La prima volta viene richiesto un indirizzo mail in modo che LetsEncrypt possa mandare dei promemoria se il certificato sta per scadere. Dovremo anche accettare i termini di servizio.

Se tutto è andato liscio dovremmo avere un output tipo questo:

Saving debug log to /var/log/letsencrypt/letsencrypt.log
 Obtaining a new certificate
 Performing the following challenges:
 http-01 challenge for webmail.example.org
 Using the webroot path /var/www/webmail.example.org for all unmatched domains.
 Waiting for verification...
 Cleaning up challenges
 Generating key (2048 bits): /etc/letsencrypt/keys/0049_key-certbot.pem
 Creating CSR: /etc/letsencrypt/csr/0049_csr-certbot.pem
IMPORTANT NOTES:
 - Congratulations! Your certificate and chain have been saved at
 /etc/letsencrypt/live/webmail.example.org/fullchain.pem. Your
 cert will expire on 2018-04-01. To obtain a new or tweaked version
 of this certificate in the future, simply run certbot again. To
 non-interactively renew *all* of your certificates, run "certbot
 renew"
 - If you like Certbot, please consider supporting our work by:
Donating to ISRG / Let's Encrypt: https://letsencrypt.org/donate
 Donating to EFF: https://eff.org/donate-le

Vi domandate cosa è successo realmente? Beh, Certbot ha creato la chiave privata/segreta (che solo il nostro server deve conoscere). Hai poi collocato un certo file in /var/www/webmail.example.org/.well-known/…, dopodiché il servizio LetsEncrypt ha visitato il vostro sito web e verificato detto file. Questa è una prova sufficiente che possediamo il dominio (perché siamo in controllo della zona DNS) e che abbiamo accesso al server web.

Apache e HTTPS

La comunicazione non criptata HTTP non è più un’opzione al giorno d’oggi. E ora che abbiamo un certificato aggiungiamo un host virtuale che gestisca l’HTTPS.

Creiamo un nuovo file /etc/apache2/sites-available/webmail.example.org-https.conf contenente:

<VirtualHost *:443>
 ServerName webmail.example.org
 DocumentRoot /var/www/webmail.example.org
 SSLEngine on
 SSLCertificateFile /etc/letsencrypt/live/webmail.example.org/fullchain.pem
 SSLCertificateKeyFile /etc/letsencrypt/live/webmail.example.org/privkey.pem
</VirtualHost>

Questa configurazione per l’host virtuale sembra fin troppo simile a quella dell’host virtuale HTTP sopra. Solamente ascolta sulla porta 443 (porta standard per HTTPS) invece della porta 80. Abilita il “SSL Engine” che gestisce la cryptazione ed ottiene le informazioni riguardo il nostro server web (mostrato a tutti gli utenti) e la chiave privata (che il server web usa per decriptare la comunicazione con l’utente).

Abilitiamo il modulo SSL in Apache:

a2enmod ssl

Abilitiamo l’host virtuale per l’HTTPS:

a2ensite webmail.example.org-https

E ricarichiamo di nuovo la configurazione:

systemctl reload apache2

Adesso se puntiamo il nostro browser web su https://webmail.example.org il browser dovrebbe dirci che si fida del certificato del sito web:

Si, scusate, questo non è webmail.example.org. Ma non possiedo il dominio example.org e quindi non posso ottenere un certificato valido per quello. Questo è il mio sito.

Dovremmo tenere il server virtuale HTTP? Si. Usiamolo per reindirizzare i nostri utenti al sito HTTPS se si dimenticano di mettere “https://” di fronte all’URL. E l’HTTP è sempre richiesto per LetsEncrypt. Quindi qual è la soluzione?

Rinnovo automatico

Ottenere un certificato è solo metà dell’opera. I certificati di LetsEncrypt scadono dopo 90 giorni. Quindi è vitale rinnovare i certificati automaticamente ed in tempo. Il pacchetto certbot aggiunge un cron job automatico in /etc/cron.d/certbot per questo scopo. Viene lanciato due volte al giorno e dopo un intervallo casuale (in modo che il servizio LetsEncrypt non riceva troppe richieste nello stesso momento) controlla se i certificati devono essere rinnovati. Questo viene fatto chiamando “certbot -q renew”. “-q” sta per “quiet” ed evita di ricevere due mail al giorno che dicono cosa certbot ha fatto.

Manca ancora un pezzo del puzzle. Anche se il rinnovo dovesse funzionare, aggiornerebbe solamente i file del certificato. Ma i componenti software – Postfix, Dovecot e Apache – non noteranno il cambiamento. Abbiamo bisogno quindi di un cosiddetto post-hook che inneschi un successivo riavvio di tutti i processi.

Creiamo un semplice script shell in /usr/local/bin/certbot-post-hook che contenga:

#!/bin/sh
service postfix restart
service dovecot restart
service apache2 restart

Rendiamolo eseguibile:

chmod u+x /usr/local/bin/certbot-post-hook

Testiamolo:

/usr/local/bin/certbot-post-hook

Non produce output. Dovrebbe solo funzionare senza errori e riavviare tutti i tre servizi che usano il certificato.

Ora editiamo il cron job automatico in /etc/cron.d/certbot ed aggiungiamo la parte evidenziata:

0 */12 * * * root test -x /usr/bin/certbot -a ! -d /run/systemd/system && perl -e 'sleep int(rand(3600))' && certbot -q --post-hook /usr/local/bin/certbot-post-hook renew

Per essere sicuri che il rinnovo funzioni possiamo simulare il processo lanciando

certbot --dry-run --post-hook /usr/local/bin/certbot-post-hook renew

Ben fatto. Abbiamo implementato LetsEncrypt per tutti i servizi. Procediamo.

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *