Installare un certificato Let's Encrypt per i server qmail e dovecot

5 agosto 2023 by Roberto Puzzanghera 7 commenti

Changelog

  • 5 agosto 2023
    L'installzione del certificato è ora basata su dehydrated. La vecchia documentazione basata su certbot si trova in fondo a questa pagina, ma non verrà più aggiornata.
  • May 18, 2023
    added the option --key-type rsa to the certbot command, to avoid that certbot will silently default to ECDSA the private key format, which results not understandable by my openssl-1.1. In this way the format of the private key will be RSA. More info here.

To enable HTTPS on your website, you need to get a certificate (a type of file) from a Certificate Authority (CA). Let’s Encrypt is a CA. In order to get a certificate for your website’s domain from Let’s Encrypt, you have to demonstrate control over the domain. With Let’s Encrypt, you do this using software that uses the ACME protocol which typically runs on your web host.

Dehydrated is a client for signing certificates with an ACME-server (e.g. Let's Encrypt) implemented as a relatively simple (zsh-compatible) bash-script. This client supports both ACME v1 and the new ACME v2 including support for wildcard certificates!

Trattandosi di un programma shell, dehydrated ha il vantaggio di non richiedere dipendenze, a differenza deI programma ufficiale certbot, che richiede una lunghissima serie di librerie python. Mantenere tutto questo volume di programmi si è rivelato faticoso nel tempo, ed è questo il motivo per cui mi sono deciso a passare a dehydrated.

Note per l'aggiornamento

Nel caso si debba rimpiazzare una installazione funzionante dei certificati basati su certbot, non è necessario prendere alcuna precauzione poichè questi non saranno sovrascritti dai nuovi generati da dehydrated. Pertanto è possibile eseguire i nostri test riguardanti la configurazione di dehydrated nello stesso server di produzione. Naturalmente sarà bene utilizzare un dominio di prova mentre si smanetta con Apache.

Installazione di dehydrated

E' probabile che la distribuzione in uso metta a disposizione un pacchetto dehydrated. In tal caso installarlo da lì, altrimenti scaricare e installare il programma dal sito github.

Qui di seguito un breve esempio di una installazione manuale in /usr/local (modificare secondo i propri bisogni):

VERSION=0.7.1
wget https://github.com/dehydrated-io/dehydrated/releases/download/v${VERSION}/dehydrated-${VERSION}.tar.gz
tar xzf dehydrated-${VERSION}.tar.gz
cd dehydrated-${VERSION}
chown -R root:root .
cp dehydrated /usr/local/bin/
mkdir -p /usr/local/man/man1 /usr/local/share/doc/dehydrated-${VERSION}/docs/examples
cp docs/man/dehydrated.1 /usr/local/man/man1/
mkdir -p /etc/dehydrated
cp docs/examples/config /etc/dehydrated/config.new # .new just to avoid overwrite of the existing config. Rename to config
cp CHANGELOG* LICENSE* README* /usr/local/share/doc/dehydrated-${VERSION}
cp docs/*.md /usr/local/share/doc/dehydrated-${VERSION}/docs
cp docs/examples/{domains.txt,hook.sh} /usr/local/share/doc/dehydrated-${VERSION}/docs/examples

Configurazione

Portarsi nella cartella /etc/dehydrated, dove abbiamo i file di configurazione e dove verranno installati i certificati. Queste le mie modifiche al file config:

CA="letsencrypt-test"
CHALLENGETYPE="http-01"
WELLKNOWN="/var/www/dehydrated"
KEY_ALGO=rsa
CONTACT_EMAIL=postmaster@mydomain.tld
  • CA contiene l'URL al server Let’s Encrypt, oppure un parametro (in questo caso letsencrypt-test) che dice al programma quale URL usare. In fase di test lasciare "letsencrypt-test" di modo che il server non venga intasato e noi bannati di conseguenza se si supera il limite di tentativi non validi. Una volta che tutto sarà a posto useremo CA="letsencrypt". Maggiori informazioni qui.
  • CHALLENGETYPE="http-01" Come sappiamo, è necessario dimostrare di avere il controllo dei domini di cui si vuole ottenere un certificato. Per fare ciò verrà testato l'accesso a un file di verifica posto nel nostro web server, in una cartella dove Apache deve avere accesso per ciascuno dei domini da certificare.
    Esistono anche altri CHALLENGETYPE, dns-01 ad esempio è adatto a certificare domini con wildcard come *.sagredo.eu, ma è necessario disporre di programmi per manipolare in automatico il server DNS. Questa parte non viene pertanto trattata qui.
  • WELLKNOWN="/var/www/dehydrated" è la cartella locale dove dehydrated installerà i ‘challenge-tokens’, che poi sarà recuperato via http al fine di validare il dominio.
  • KEY_ALGO=rsa specifica l'algoritmo da usare per la chiave pubblica.

dehydrated è in grado di lanciare un programa a nostra scelta dopo l'avvenuta creazione del certificato (HOOK="${BASEDIR}/hook.sh"). Noi faremo a meno di questa opportunità e creeremo manualmente un file che gestirà la post-installazione del certificato. Ho notato infatti che, durante la creazione del certificato, dehydrated lancia più volte hook.sh, cosa per nulla soddisfacente.

Per usare dehydrated è necessario registrare un account:

# dehydrated --register --accept-terms 
# INFO: Using main config file /etc/dehydrated/config 
+ Generating account key... 
+ Registering account key with ACME server... 
+ Fetching account URL... 
+ Done!

Le informazioni riguardanti l'account vengono salvate nella cartella /etc/dehydrated/accounts.

Configurazione dei domini

Creare un file domains.txt nel quale disporre i domini da certificare separati da uno spazio bianco. Si possono inserire domini su righe separate. Quelli che stanno sulla stessa riga faranno capo a uno stesso certificato, il cui nome sarà quello del primo dominio della riga. Ad esempio

mx.mydomain.tld
mydomain.tld www.mydomain.tld webmail.mydomain.tld otherdomain.tld www.otherdomain.tld webmail.otherdomain.tld

creerà due certificati mx.mydomain.tld e mydomain.tld.

In aggiunta verranno letti tutti gli eventuali file con estensione txt posti nella cartella /etc/dehydrated/domains.d.

Configurazione di Apache

In un caso tipico dovremo certificare molti domini, alcuni dei quali dedicati al server di posta, altri a dei semplici spazi web (per esempio la webmail o il pannello di controllo qmailadmin) ognuno con il proprio VirtualHost e la propria cartella radice DocumentRoot. Faremo in modo di salvare i ‘challenge-tokens’ in una medesima cartella accessibile a tutti questi domini, diciamo /var/www/dehydrated, che è quella indicata dal parametro WELLKNOWN nel file di configurazione.

Creiamo innanzitutto la suddetta cartella:

mkdir -p /var/www/dehydrated

Il codice da aggiungere è ripetitivo ed è conveniente automatizzare il tutto salvandolo in un file redirect.conf da importare in ciascun VirtualHost. Salviamolo nella cartella di configurazione di Apache, ovvero /etc/httpd:

cat > /etc/httpd/redirect.conf << __EOF__
<IfModule mod_rewrite.c> 
  RewriteEngine On 
  RewriteCond %{REQUEST_URI} !^/.well-known/acme-challenge 
  RewriteRule ^(.*) https://%{SERVER_NAME}\$1 [R,L] 
</IfModule> 

Alias /.well-known/acme-challenge /var/www/dehydrated
<Directory /var/www/dehydrated>
  Options None 
  AllowOverride None 
  Require all granted 
</Directory>

# Define or change \${LOGDIR} to where your server saves the logs
CustomLog "\${LOGDIR}/dehydrated_access.log" combined
ErrorLog  "\${LOGDIR}/dehydrated.f2b.log"
__EOF__

Così facendo le richieste per i file del tipo /.well-known/acme-challenge/* saranno servite nella cartella /var/www/dehydrated, mentre il resto del traffico verrà reindirizzato (in questo esempio) all'indirizzo https con lo stesso dominio (SERVER_NAME). Come si può vedere, ciò presuppone che il modulo mod_rewrite di Apache sia stato abilitato.

Sempre per questioni di ordine e di economia di codice, converrà definire, nel file generale di configurazione /etc/httpd.conf o dove si preferisce, alcune variabili, ad esempio il percorso del file da includere e, visto che ci siamo, il file che useremo in seguito per importare i certificati SSL e la cartella che andrà a ospitare i certificati:

Define REDIRECT /etc/httpd/redirect.conf
Define SSL      /etc/httpd/ssl.conf
Define CERTDIR  /etc/dehydrated/certs

Ecco uno schema del virtual host relativo al dominio che porta al nostro server di posta:

<VirtualHost *:80> 
  ServerName mx.mydomain.tld
  Include \${REDIRECT}
</VirtualHost>

Creazione del certificato

Non ci resta che creare il certificato:

# dehydrated -c 
# INFO: Using main config file /etc/dehydrated/config 
Processing mx.mydomain.tld 
+ Creating new directory /etc/dehydrated/certs/mx.mydomain.tld ... 
+ Signing domains... 
+ Generating private key... 
+ Generating signing request... 
+ Requesting new certificate order from CA... 
+ Received 1 authorizations URLs from the CA 
+ Handling authorization for mx.mydomain.tld 
+ 1 pending challenge(s) 
+ Deploying challenge tokens... 
+ Responding to challenge for mx.mydomain.tld authorization... 
+ Challenge is valid! 
+ Cleaning challenge tokens... 
+ Requesting certificate... 
+ Order is processing... 
+ Checking certificate... 
+ Done! 
+ Creating fullchain.pem... 
+ Done!

Dovremo ottenere un risultato simile per ogni certificato richiesto (uno per ogni riga in domains.txt). I certificati vengono salvati nella cartella certs, di cui abbiamo registrato l'indirizzo nel parametro CERTDIR. Usare il man o anche dehydrated -h per vedere come cancellare o revocare i certifcati.

Una volta che la procedura di creazione dei certificati è andata a buon fine possiamo impostare dehydrated affinchè si colleghi all'indirizzo di produzione (CA="letsencrypt" nel file config).

A questo punto i certificati non sono ancora visti nè dal web-server, nè da qmail e nè da dovecot.

Installazione del certificato su Apache

Per quanto riguarda Apache, creiamo un file con le impostazioni SSL da importare in ogni VirtualHost:

cat > /etc/httpd/ssl.conf << __EOF__
SSLEngine on 
SSLCertificateFile \${CERTDIR}/\${CERTNAME}/fullchain.pem 
SSLCertificateKeyFile \${CERTDIR}/\${CERTNAME}/privkey.pem 
SSLCertificateChainFile \${CERTDIR}/\${CERTNAME}/fullchain.pem
__EOF__

CERTNAME è il nome del certificato, da passare prima di includere il file, come da esempio qui sotto. CERTDIR l'abbiamo già definito più sopra.

Questo è un esempio di VirtualHost configurato per ospitare delle pagine web in https, ad esempio per la webmail:

<VirtualHost *:80> 
  ServerName webmail.mydomain.tld
  ServerAlias webmail.otherdomain.tld
  Include ${REDIRECT} 
</VirtualHost> 

<VirtualHost *:443> 
  # The name of the certificate is the first domain of the line in /etc/dehydrated/domains.txt
  Define CERTNAME mydomain.tld
  # SSL cannot work until the certificate is in place. Comment it out initially
  Include ${SSL} 

  ServerName webmail.mydomain.tld
  ServerAlias webmail.otherdomain.tld

  ErrorLog  ${LOGDIR}/roundcube_error.log 
  CustomLog ${LOGDIR}/roundcube_access.log combined 

  DocumentRoot ${HTDOCS}/roundcube

  <Directory ${HTDOCS}/roundcube> 
    Require all granted 
  </Directory> 
</VirtualHost>

Installazione del certificato su qmail e dovecot

Preparare uno script che lanci dehydrated e gestisca l'installazione dei certificati. Salviamolo in/usr/local/bin/my_dehydrated.sh:

cat > /usr/local/bin/my_dehydrated.sh << __EOF__
#!/bin/sh 

CERTNAME=mx.mydomain.tld 
CERTDIR=/etc/dehydrated/certs/\${CERTNAME} 
QMAILDIR=/var/qmail 
QMAILCTL=/usr/local/bin/qmailctl 
DOVECOTCTL=/usr/local/bin/dovecotctl 
APACHECTL=/usr/sbin/apachectl 
DEHYDRATED=/usr/bin/dehydrated 

# cert renewal 
\$DEHYDRATED -c 

if [ \$? -eq 0 ]; then 
  # backup del certificato per qmail 
  if [ ! -d "\${QMAILDIR}/control/certs_backup" ]; then 
    mkdir -p \${QMAILDIR}/control/certs_backup 
  fi 
  echo "Setting up the cert for qmail" 
  cp -p \${QMAILDIR}/control/*.pem \${QMAILDIR}/control/certs_backup/ 
  cat \${CERTDIR}/privkey.pem \${CERTDIR}/fullchain.pem > \${QMAILDIR}/control/servercert.pem 
  chown vpopmail:vchkpw \${QMAILDIR}/control/*.pem 
  chmod o-r \${QMAILDIR}/control/*.pem 
  \$QMAILCTL restart 

  # restart dovecot 
  echo "Restarting dovecot" 
  \$DOVECOTCTL stop 
  sleep 5 
  \$DOVECOTCTL start 

  # restart apache 
  echo "Restarting apache" 
  \$APACHECTL -k graceful 

  exit 0 
else exit 1 
fi
__EOF__

chmod +x /usr/local/bin/my_dehydrated.sh

Come sappiamo, il certificato di qmail (file control/servercert.pem) è il risultato della concatenazione della chiave privata e della fullchain. Per quanto riguarda qmail non dobbiamo fare altro.

Riguardo a Dovecot, invece, è necessario impostare correttamente l'indirizzo dei certificati nel file /usr/local/dovecot/etc/dovecot/conf.d/10-ssl.conf:

ssl_cert = </etc/dehydrated/certs/mx.mydomain.tld/fullchain.pem
ssl_key = </etc/dehydrated/certs/mx.mydomain.tld/privkey.pem

Letsencrypt raccomanda di rinnovare automaticamente i certificati quando sono a circa un terzo dal loro fine vita, che al momento è 90 giorni. Questo significa che è necessario rinnovarli a 30 giorni dalla scadenza Settiamo dunque il cronjob affinchè lanci lo script una volta al mese:

cat > /etc/cron.d/dehydrated << __EOF__
40 2 6 * * /usr/local/bin/my_dehydrated.sh >> /var/log/cron 2>&1
__EOF__

Installazione di certbot

La documentazione su certbot non è più aggiornata in quanto soppiantata da quella basata su dehydrated. Viene lasciata intatta in caso possa ancora essere di aiuto a qualcuno.

Qui di seguito viene spiegato come installare e configurare un certificato SSL valido di Let's Encrypt per i server qmaildovecot. L'installazione è ad opera del client certbot.

Certbot is part of EFF’s effort to encrypt the entire Internet. Secure communication over the Web relies on HTTPS, which requires the use of a digital certificate that lets browsers verify the identity of web servers (e.g., is that really google.com?). Web servers obtain their certificates from trusted third parties called certificate authorities (CAs). Certbot is an easy-to-use client that fetches a certificate from Let’s Encrypt—an open certificate authority launched by the EFF, Mozilla, and others—and deploys it to a web server.

Maggiori informazioni qui:

Innanzitutto è necessaria una versione di python v.3, e poi vi sono una marea di prerequisiti, perciò è consigliabile lasciar fare l'installazione al package manager della propria distribuzione. Per gli utenti Slackware c'è uno sclackbuild pronto su SBO qui e se non si ha voglia di risolvere manualmente tutte le dipendenze si può sempre usare sbotools.

Installazione del certificato

Naturalmente il certificato viene rilasciato dopo che si è data prova delle affettiva proprietà del dominio associato al certificato. Pertanto certbot dovrà installare una "ACME challenge" (ovvero un file con un nome riconoscibile) in una directory a nostra scelta dove far girare un webserver temporaneo e recuperare l'ACME via http. Se tutto va a buon fine il certificato verrà installato in /etc/letsencrypt.

Creiamo quindi la cartella dove "webroot" la ACME challenge dovrà essere salvata:

mkdir -p /path/to/webroot

Creare un virtual host apposito su apache. yourdomain.tld è il dominio al quale faremo la connessione smtp e imap/pop3:

<VirtualHost *:80>
 ServerName yourdomain.tld

DocumentRoot /path/to/webroot
 <Directory /path/to/webroot>
   Require all granted
 </Directory>
</VirtualHost>

Prepariamo uno script per installare i certificati via certbot in /usr/local/bin/my_certbot.sh: 

cat > /usr/local/bin/my_certbot.sh << __EOF__
#!/bin/sh
#

CERTBOT=/usr/bin/certbot
DOMAIN=mydomain.tld

\$CERTBOT certonly \\
 --webroot \\
 --webroot-path /path/to/webroot \\
 --preferred-challenges http-01 \\
 --key-type rsa \\
 -d \${DOMAIN} \\
 --email myemail@\${DOMAIN} \\
 --renew-by-default \\
 --agree-tos \\
 --text

# qmail cert
if [ ! -d "/var/qmail/control/certs_backup" ]; then
 mkdir -p /var/qmail/control/certs_backup
fi
cp -p /var/qmail/control/*.pem /var/qmail/control/certs_backup/
cat /etc/letsencrypt/live/\${DOMAIN}/privkey.pem /etc/letsencrypt/live/\${DOMAIN}/fullchain.pem > /var/qmail/control/servercert.pem
chown vpopmail:vchkpw /var/qmail/control/*.pem 
chmod o-r /var/qmail/control/*.pem
/usr/local/bin/qmailctl restart

# dovecot cert (you have to set the path inside 10-ssl.conf accordingly)
/usr/local/bin/dovecotctl restart
__EOF__

chmod +x /usr/local/bin/my_certbot.sh

mydomain.tld sarà usato come nome del certificato stesso. Per conoscere meglio cosa può fare certbot si può digitare:

certbot --help all

Ricordiamoci infine di settare la x flag:

chmod +x /usr/local/bin/my_certbot.sh

Possiamo quindi eseguire lo script e se non vi saranno errori avremo ottenuto il nostro certificato.

Infine settiamo un cronjob per rinnovare il certificato una volta al mese (la validità è di 3 mesi):

15 2 20 * * /usr/local/bin/my_certbot.sh >> /var/log/cron

Ricordare di disabilitare la linea di update_tmprsadh nel crontab.

Configurazione di qmail e dovecot

Per quanto riguarda qmail la private key e la fullchain devono essere unite in un unico file /var/qmail/control/servercert.pem. Questo viene fatto dallo script di cui sopra e non deve essere fatto altro.

Riguardo a dovecot invece, è sufficiente modificare il file di configurazione /usr/local/dovecot/etc/dovecot/conf.d/10-ssl.conf come segue:

#ssl_cert = </etc/ssl/certs/dovecot.pem
#ssl_key = </etc/ssl/private/dovecot.pem
ssl_cert = </etc/letsencrypt/live/yourdomain.tld/fullchain.pem
ssl_key = </etc/letsencrypt/live/yourdomain.tld/privkey.pem

Ora riavviare qmail e dovecot per abilitare il nuovo certificato.

Commenti

Differenze dei certificati autogenerati e certbot

La differenza tra autogerenato e Certbot è che il primo non è referenziato da una root e pertanto è definito comunque inattendibile, il secondo essendo attaccato alla radice root è valido perchè validato dal root. Ringraziamo con una donazione questa org che pur con limitazioni mette a disposizione i propri server per la gestione della autorizzazioni facendosi carico del costo del traffico dati.

Una news di pochi giorni fà: Scaduti i miei certificati autogenerati ho eseguito il rinnovo autogenerandolli come faccio da oltre 12 Anni da quando i miei server sono attivi con questa installazione (grazie ai ragazzi di sagredo per il lungo supporto) e di alcuni clienti che mi  hanno affidato la gestione in sicurezza delle loro Mail Machine.  Ci sono porblemi con le piattaforme Apple iMac(mail) e Mail Iphone che rifiutano a priori i certificati non attendibili e se per mac rimane la possibilità di confermare che vanno bene sugli iPhone hanno tolto (ritengo con le ultime upgrade)  la spunta "Autorizza" quando si visualizzano i dettagli del certificato autogenerato. Upgradando tutti i server con i certificati Certbot la questione si è risolta. Grazie per questa guida che integrerei con l'install del certificato SSL per Dovecot

Rispondi |

Differenze dei certificati autogenerati e certbot

Ciao, per quanto riguarda dovecot, come scritto sopra, la sola cosa da fare è settare i seguenti parametri e il gioco è fatto

ssl_cert = </etc/letsencrypt/live/smtp.yourdomain.tld/fullchain.pem
ssl_key = </etc/letsencrypt/live/smtp.yourdomain.tld/privkey.pem

Rispondi |

differenza tra fullchain e certificato

Ciao Roberto, che differenza c'è nell'usare la fullchain al posto del certificato?

E cosa succede per i client se cambio la configurazione in un server di produzione?

Grazie

Gabriele

Rispondi |

differenza tra fullchain e certificato

non sono sicuro di aver capito bene la domanda.. con certificato intendi servercert.pem? quest'ultimo è la fusione del fullchain e della chiave privata, ad es.

cat /etc/letsencrypt/live/smtp.${DOMAIN}/privkey.pem /etc/letsencrypt/live/smtp.${DOMAIN}/fullchain.pem > /var/qmail/control/servercert.pem

il client dovrebbe assorbire in modo indolore la variazione del certificato, se questo è valido, a meno che non sia settato per fornire comunque una notifica all'utente (claws ad es. ha un'opzione del genere)

Rispondi |

differenza tra fullchain e certificato

La documentazione di Dovecot non indica di usare la fullchain  ma il certifcato (o auto generato o acquistato) nella configurazione del SSL, e così ho fatto fino a quando non ho inizaito ad avere come riferimento la tua utilissima guida.

Per quello mi domandavo se ci fossero delle differenze nell'usare fullchain  o certificato nella configurazione di Dovecot.

Grazie

Rispondi |

differenza tra fullchain e certificato

Ti posso assicurare che la configurazione come la descrivo sopra funziona. Non ricordo più dove ho trovato esempi identici...

Rispondi |

differenza tra fullchain e certificato

Si funziona, la sto usando, ero curioso di conoscere la differenza delle 2 configurazioni.

Grazie ancora

Rispondi |

Aggiungi un commento