====== Certificati Let's Encrypt (certbot) ====== [[https://letsencrypt.org/|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/''**. È 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/''**. 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 [[https://community.letsencrypt.org/t/grouping-www-example-com-and-example-com-domains/6255/8|Let's Encrypt Forum]] e [[https://github.com/certbot/certbot/pull/2809|GitHub request 2809]]. NOTA: Sembra che il problema sia risolto a partire dalla versione 0.6.0 del client, questo dovrebbe essere il [[https://github.com/certbot/certbot/pull/2809/commits/9111faeb942129cf2831be3ae695b5e7b5bc5b06|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/-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 **[[https://community.letsencrypt.org/t/how-to-prevent-creation-of-etc-letsencrypt-live-domain-tld-0001-when-removing-domains-from-a-domain-tld-multidomain-certificate/8135/3|post]]** e questo **[[https://github.com/certbot/certbot/issues/2071|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/-0001/** Rinominare la directory. * **/etc/letsencrypt/live/-0001/** Modificare i link simbolici contenuti. * **/etc/letsencrypt/live/-0001/** Rinominare la directory. * **/etc/letsencrypt/renewal/-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: SSLEngine off ServerName mail.rigacci.org RedirectMatch permanent /(.*) https://mail.rigacci.org/mail/ 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: SSLEngine off ServerName mail.rigacci.org DocumentRoot /var/www/html/http2https ErrorDocument 404 /404.php e nella DocumentRoot ci saranno due file: **index.php** **404.php** ===== 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 [[https://ssl-tools.net/mailservers|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 ; 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 [[authdaemon_problem#problema_con_dhparamspem_e_ssl|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 **[[https://letsencrypt.org/docs/dst-root-ca-x3-expiration-september-2021/|DST Root CA X3 Expiration (September 2021)]]**