User Tools

Site Tools


doc:appunti:linux:sa:letsencrypt

Certificati Let's Encrypt (certbot)

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:

  • Scarica un challenge e lo pubblica via web sul dominio che si vuole certificare.
  • Richiede alla Certification Authority di verificare il challenge.
  • Riceve il certificato (valido per il dominio in questione) e lo salva in /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.

Installazione su Debian Jessie

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

Richiesta dei certificati: modalità test

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/.

Richiesta dei certificati: modalità produzione

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.

Estensione del certificato a più nomi a dominio

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.

Rimozione di un nome di dominio dai Subject Alternative Names

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:

  • /etc/letsencrypt/archive/<domain>-0001/ Rinominare la directory.
  • /etc/letsencrypt/live/<domain>-0001/ Modificare i link simbolici contenuti.
  • /etc/letsencrypt/live/<domain>-0001/ Rinominare la directory.
  • /etc/letsencrypt/renewal/<domain>-0001.conf Rinominare il file e modificare il contenuto.

Redirect automatico da http a https

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");
?>

Directory protetta da .htaccess

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

Rinnovo dei certificati

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

Reload di Apache

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.

Utilizzo dei certificati con Exim4

È 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

Utilizzo dei certificati con Postfix

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.

Certificati TLS come server

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

Certificati TLS come client

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

Verifica del certificato SMTP con STARTTLS

È 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.

Utilizzo dei certificati con Courier POP e IMAP

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

  • /etc/courier/pop3d.pem
  • /etc/courier/imapd.pem

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.

Verifica dei certificati POP/IMAP

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.

Verifica dei certificati HTTPS

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

Certificato DST Root CA X3 scaduto

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.

Vedere DST Root CA X3 Expiration (September 2021)

doc/appunti/linux/sa/letsencrypt.txt · Last modified: 2022/04/01 07:41 by niccolo