Let’s Encrypt è una Autorità di Certificazione gratuita, automatica e aperta. Consente cioè di ottenere certificati SSL (ad esempio per i siti https) in modo automatico e gratuito.
Per Debian GNU/Linux esiste il client certbot che deve essere eseguito sullo stesso host che ospita il webserver. In pratica lo script dialoga con la Certification Authority ed effettua le seguenti operazioni:
/etc/letsencrypt/archive/<dominio>
.È possibile anche estendere il certificato in modo che comprenda diversi nomi a dominio. In questo modo un unico certificato è valido per diversi VirtualHost Apache.
Un certificato rilasciato da Let's Encrypt può essere utilizzato anche per la crittografia SSL del server SMTP Exim4.
Per Debian Jessie il pacchetto certbot esiste nei jessie-backports. Le dipendenze sono molte e ogni tanto la compilazione dei backports fallisce (il pacchetto non esiste sul repository), conviene quindi scaricare e salvare tutte le dipendenze backports in locale. Questo l'elenco dei pacchetti backports che si è dovuto scaricare per installare certbot 0.8.0 su Debian Jessie:
certbot python-acme python-certbot python-cffi-backend python-configargparse python-cryptography python-dialog python-idna python-ipaddress python-openssl python-psutil python-pyasn1 python-rfc3339
Questa è la riga di comando per scaricare dei certificati di test (per i certificati di test non ci sono limiti di richieste giornaliere):
certbot certonly --text --test-cert --webroot -w "/var/www/html/www.rigacci.org" -d "www.rigacci.org"
Lo script deve avere accesso alla DocumentRoot del dominio per scrivere temporaneamente il challenge. Viene creata a tal scopo una sottodirectory di nome .well-known
. Se tutto funziona il certificato verrà salvato in /etc/letsencrypt/archive/www.rigacci.org/
.
In modo del tutto simile si ottiene il certificato effettivo:
certbot certonly --text --webroot -w "/var/www/html/www.rigacci.org" -d "www.rigacci.org"
Nella configurazione Apache andranno aggiunte le direttive:
SSLCertificateFile /etc/letsencrypt/live/www.rigacci.org/fullchain.pem" SSLCertificateKeyFile /etc/letsencrypt/live/www.rigacci.org/privkey.pem"
È lo script certbot che si occupa di mantenere il link simbolico dalla directory live alla directory archive.
Se si desidera estendere il certificato ad altri nomi a dominio questa è la riga di comando:
certbot certonly --text --webroot \ -w "/var/www/html/www.rigacci.org" -d "www.rigacci.org" \ -w "/var/www/html/mail.rigacci.org" -d "mail.rigacci.org"
ATTENZIONE: Conviene eseguire lo script la prima volta con solo il dominio principale, in modo che il nome della directory creata sarà /etc/letsencrypt/archive/<dominio>
. Invocando certbot con nomi di dominio aggiuntivi, lo script chiederà conferma se si vuole estendere il certificato esistente, in caso affermativo questi saranno aggiunti.
C'è un solo inconveniete: il certificate subject verrà scelto in maniera casuale fra tutti i nomi elencati, senza privilegiare il nome principale (quello dichiarato per primo). Questo potrebbe anche essere un bug, vedi Let's Encrypt Forum e GitHub request 2809. NOTA: Sembra che il problema sia risolto a partire dalla versione 0.6.0 del client, questo dovrebbe essere il commit relativo.
Se si desidera togliere un nome di dominio dall'elenco dei nomi alternativi SAN (Subject Alternative Names), si deve eseguire nuovamente il comando certbot certonly passando il nuovo elenco (ridotto) dei nomi e relative web root.
C'è tuttavia un inconveniente (ancora con certbot v.0.31): alla successiva esecuzione di certbot certonly viene creata una nuova lineage di certificati in una cartella appositamente creata: /etc/letsencrypt/archive/<domain>-0001/
, anche nella directory /etc/letsencrypt/live/
venono creati i link simbolici sotto una nuova directory con il suffisso -0001
. Ovviamente i vari software (Apache, Postfix, ecc.) continueranno ad utilizzare la vecchia lineage di certificati.
Vedere in proposito questo post e questo bug.
È possibile eliminare manualmente la vecchia lineage e rinominare quella nuova togliendo il suffisso. Fare attenzione a tutte le modifiche da fare:
Alcuni siti possono avere il redirect automatico da http ad https con una direttiva Redirect di Apache. Ad esempio:
<VirtualHost *:80> SSLEngine off ServerName mail.rigacci.org RedirectMatch permanent /(.*) https://mail.rigacci.org/mail/ </VirtualHost>
Questo rende impossibile il funzionamento di certbot che si basa sul fatto di poter pubblicare temporaneamente il challenge sul dominio web (senza SSL).
La soluzione più elegante può essere quella di effettuare il redirect ad eccezione per la .well-known directory:
RedirectMatch permanent ^/((?!\.well-known).*)$ https://mail.rigacci.org/$1
Una alternativa può essere quella di creare una DocuemtnRoot ad-hoc, che effettui il redirect su hpps via PHP invece che con direttiva Apache. Questa stessa DocumentRoot sostanzialmente vuota può essere condivisa da diversi VirtualHost, anche con nomi a dominio diversi. La configurazione Apache diventa:
<VirtualHost *:80> SSLEngine off ServerName mail.rigacci.org DocumentRoot /var/www/html/http2https ErrorDocument 404 /404.php </VirtualHost>
e nella DocumentRoot ci saranno due file:
index.php
<?php $redirect_location = 'https://' . $_SERVER['SERVER_NAME'] . '/'; header("Location: $redirect_location"); ?>
404.php
<?php $redirect_location = 'https://' . $_SERVER['SERVER_NAME'] . $_SERVER['REQUEST_URI']; header("Location: $redirect_location"); ?>
Se un intero sito è protetto da una direttiva tipo AuthType Basic (ad esempio con una accoppiata di file .htaccess e .htpasswd), la procedura di certbot fallisce perché il server remoto non è in grado di accedere via HTTP alla sottodirectory /.well-known/ creata appositamente (nella quale viene creato il challenge provvisorio).
È quindi necessario escludere la sottodirectory /.well-known/ dalla direttiva AuthType Basic, ad esempio creando un apposito file .htaccess che contiene:
AuthType None Require all granted
Con il semplice comando
certbot renew
si verifica e si rinnovano tutti i certificati contenuti in /etc/letsencrypt/live/
. Eventualmente si aggiunge l'opzione -q
per fare un cronjob che non genera messaggi inutili.
Il pacchetto Debian 9 Stretch di certbot installa un cronjob /etc/cron.d/certbot che però non viene eseguito poiché è attiva la gestione dei processi di systemd. Infatti risulta registrato con systemd il certbot.timer, che provvede ad eseguire l'aggiornamento a intervalli regolari.
Verificare che il timer sia abilitato e attivo:
systemctl enable certbot.timer systemctl start certbot.timer systemctl status certbot.timer
Dopo aver esteso un certificato (e quindi anche dopo un rinnovo automatico?) è necessario notificare il demone apache almeno con un reload, ad esempio con systemctl reload apache2.service.
È sufficiente copiare il certificato e la chiave nei rispettivi file attesi da Exim. Non si possono utilizzare link simbolici perchè i file creati da certbot non hanno i permessi giusti.
cat /etc/letsencrypt/live/www.rigacci.org/fullchain.pem > /etc/exim4/exim.crt cat /etc/letsencrypt/live/www.rigacci.org/privkey.pem > /etc/exim4/exim.key chown root:Debian-exim /etc/exim4/exim.crt /etc/exim4/exim.key chmod 640 /etc/exim4/exim.crt /etc/exim4/exim.key systemctl reload exim4.service
Con i permessi predefiniti Postfix riesce a leggere i certificati direttamente dalla directory di Let's Encrypt (provato con Debian versione da 9 a 11). Se il file certificato viene aggiornato è necessario fare un reload del demone.
Per offrire TLS ai clienti che si connettono è sufficiente mettere in /etc/postfix/main.cf
:
smtpd_tls_cert_file = /etc/letsencrypt/live/www.rigacci.org/fullchain.pem smtpd_tls_key_file = /etc/letsencrypt/live/www.rigacci.org/privkey.pem
Conviene verificare il livello di crittografia offerto dal server e disabilitare tutti i sistemi deboli o difettosi. Esistono diversi servizi on-line che consentono di fare il check, ad esempio ssl-tools.net.
Alcuni algoritmi di crittografia utilizzano i parametri di Diffie-Hellman e per avere una sicurezza accettabile richiedono più di 1024 bit. L'impostazione predefinita (almeno su Debian Jessie) è invece limitata a 1024 bit.
Questo il comando necessario a generare un file DH di 2048 bit:
openssl dhparam -out /etc/postfix/dh2048.pem 2048
Queste le impostazioni da mettere in /etc/postfix/main.cf
per utilizzare il file DH appena generato e per disabilitare i metodi di crittografia anonimi:
smtpd_tls_dh1024_param_file = /etc/postfix/dh2048.pem smtpd_tls_exclude_ciphers = aNULL, RC4
Per utilizzare TLS quando si effettua il relay ad altri server è necessario mettere quanto segue in /etc/postfix/main.cf
:
# Use TLS as a client, when the relaying server supports it. smtp_tls_security_level = may smtp_tls_cert_file = /etc/letsencrypt/live/supermail.texnet.it/fullchain.pem smtp_tls_key_file = /etc/letsencrypt/live/supermail.texnet.it/privkey.pem
Se si preferisce attivare TLS solo verso alcuni host è possibile usare la direttiva smtp_tls_policy_maps in questo modo:
# Use TLS as a client, only for some relay hosts. smtp_tls_security_level = none smtp_tls_cert_file = /etc/letsencrypt/live/supermail.texnet.it/fullchain.pem smtp_tls_key_file = /etc/letsencrypt/live/supermail.texnet.it/privkey.pem smtp_tls_policy_maps = hash:/etc/postfix/smtp_tls_policy_maps
Il file /etc/postfix/smtp_tls_policy_maps deve contenere l'elenco dei domini con una impostazione più restrittiva di none, ad esempio may oppure encrypt (il file deve essere compilato con postmap):
gmail.com may rigacci.org encrypt
Lato ricevente si può verificare che il trasporto sia avvenuto utilizzando crittografia TLS; negli header del messaggio deve risultare ESMTPS invece di ESMTP:
Received: from mail.mydomain.org (mail.mydomain.org [68.129.233.182]) by mail.rigacci.org (Postfix) with ESMTPS id 875378008E for <niccolo@rigacci.org>; Thu, 31 Mar 2022 10:39:43 +0200 (CEST)
Queste sono acluni degli acronimi per i vari protocolli di trasporto email:
ESMTP | Extended Simple Mail Transfer Protocol (aggiunge security, authentication, etc. a SMTP) |
---|---|
ESMTPS | ESMTP con STARTTLS |
ESMTPSA | ESMTP con STARTTLS e SMTP AUTH |
È possibile utilizzare una installazione Nagios per verificare il corretto funzionamento del certificato, il plugin check_smtp installato con il pacchetto monitoring-plugins-basic può essere invocato direttamente (il parametro -D indica il numero minimo di giorni di validità, al di sotto dei quali scatta il warning):
/usr/lib/nagios/plugins/check_smtp -H mail.rigacci.org --port=25 --starttls -D 28 OK - Certificate 'mail.rigacci.org' will expire on Sun 10 Sep 2017 08:52:00 AM CEST.
I pacchetti Debain courier-pop-ssl e courier-imap-ssl forniscono rispettivamente gli script mkpop3dcert e mkimapdcert che provvedono a creare i certificati autofirmati e salvarli in
Per utilizzare invece i certificati Let's Encrypt è sufficiente accodare i due file privkey.pem e fullchain.pem dentro il file letto da Courier. Nelle vecchie distribuzioni Debian (prima della 8 Jessie) si doveva accodare a questo file anche i parametri DH, che adesso invece vengono letti separatamente da /etc/courier/dhparams.pem
; verificare che questo file contenga almeno 2048 bit, altrimenti si incappa nell'errore SSL3_READ_BYTES.
Non è necessario eseguire il reload dei demoni Courier, sembra che il certificato venga ricaricato al volo quando viene modificato.
Questo può essere uno script per generare il nuovo certificato, se il PEM di Let's Encrypt è stato aggiornato:
#!/bin/sh SRC_KEY='/etc/letsencrypt/live/mail.rigacci.org/privkey.pem' SRC_CRT='/etc/letsencrypt/live/mail.rigacci.org/fullchain.pem' DST_PEM='/etc/courier/letsencrypt.pem' fingerprint_src="$(/usr/bin/openssl x509 -fingerprint -noout -in "$SRC_CRT")" fingerprint_dst="$(/usr/bin/openssl x509 -fingerprint -noout -in "$DST_PEM")" || true if [ "$fingerprint_src" != "$fingerprint_dst" ]; then cat "$SRC_KEY" "$SRC_CRT" > "$DST_PEM" fi
Il file .pem viene indicato con la direttiva TLS_CERTFILE nei file /etc/courier/imapd-ssl e /etc/courier/pop3d-ssl.
Attenzione ai permessi: il certificato non deve essere leggibile al mondo e con Debian 10 bisogna che il file sia leggibile all'utente courier.
Anche la verifica del certificato SSL per il protocollo POP può essere fatta con il plugin Nagios check_pop. Sembra che il check vada fatto sulla porta 995/tcp pop3s (il plugin non supporta STARTTLS sulla porta 110?), quindi il demone deve essere in ascolto su quella porta:
/usr/lib/nagios/plugins/check_pop -H mail.rigacci.org --port=995 -D 28 OK - Certificate 'mail.rigacci.org' will expire on Sat 12 Jun 2021 10:57:00 AM CEST.
La stessa cosa vale per il protocollo IMAP:
/usr/lib/nagios/plugins/check_imap -H mail.rigacci.org --port=993 -D 28 OK - Certificate 'mail.markcommunication.com' will expire on Sat 12 Jun 2021 10:57:00 AM CEST.
La verifica del certificato SSL per il protocollo HTTPS può essere fatta con il plugin Nagios check_http:
/usr/lib/nagios/plugins/check_http --ssl -H 'www.rigacci.org' -I '176.9.39.130' -C 28
Il 30 settembre 2021 è scaduto il certificato ST Root CA X3, si tratta di un certificato root utilizzato per cross-firmare molti certificati SSL rilasciati in passato da Let's Encrypt. I nuovi certificati sono invece firmati con il nuovo certitificato ISRG Root X1, che però potrebbe non essere riconosciuto dai client un po' datati.
Anzitutto conviene confermare che il certificato in uso al server non sia scaduto e che sia firmato con il nuovo ISRG Root X1:
openssl x509 -text -noout -in /etc/letsencrypt/live/domain.tld/chain.pem
Dovrebbe risultare quanto segue:
... Signature Algorithm: sha256WithRSAEncryption Issuer: C = US, O = Internet Security Research Group, CN = ISRG Root X1 Validity Not Before: Sep 4 00:00:00 2020 GMT Not After : Sep 15 16:00:00 2025 GMT ...
Sul client invece si verifica l'errore; ad esempio, utilizzando wget da una Debian 10.3 per accedere una risorsa https, si ottiene qualcosa del genere:
ERRORE: il certificato di "www.rigacci.org" non è fidato. ERRORE: Il certificato di "www.rigacci.org" è scaduto.
Quindi su una Debian 10 è stato necessario aggiornare il seguente pacchetto:
libgnutls30 3.6.7-4+deb10u2 => 3.6.7-4+deb10u7
Su una Debian 9 invece occorre il pacchetto che si trova attualmente in stretch/updates:
libgnutls30 3.5.8-5+deb9u5 => 3.5.8-5+deb9u6
Con una CentOS 7 invece è stato necessario aggiornare il pacchetto ca-certificates.