Utilizzare letsencrypt.sh per gestire certificati SSL generici senza utilizzare un webserver

From RVM Wiki
Jump to navigation Jump to search

Il client standard di letsencrypt necessita di molte dipendenze e non agevole per richiedere certificati non utilizzati con webserver (Ad esempio per server SMTP o IMAP), perchè richiede che sia accessibile un webserver per verificare la richiesta del certificato.

Si può quindi utilizzare il client letsencrypt.sh, cheè un semplice file bash, che richiede solo openssl e poco altro.

Inoltre questo client supporta il challenge dns-01 che permette di autenticare le richieste facendo uso di un record TXT

Naturalmente per utilizzare questo challenge, è necessario avere accesso alla gestione del DNS, e preferibilemnte, avere la possibilità di aggiornare dei record TXT da script.

Predisposizione server DNS

Se si vuole utilizzare una procedura automatica per la richiesta ed il rinnovo, se si ha un server DNS bind, si può utilizzare nsupdate per crear eil record TXT richiesto.

Vedere Creazione di un sistema DDNS con Bind

Configurazione ambiente

  • Creare uno user di sistema apposito
sudo adduser --system --force-badname letsencrypt.sh
sudo usermod -d /etc/letsencrypt.sh  letsencrypt.sh
  • Creare le directories necessarie:
sudo mkdir -p  /etc/letsencrypt.sh/{hooks,cron,config}
sudo touch /etc/letsencrypt.sh/config/dummy.sh
sudo chown -R letsencrypt.sh  /etc/letsencrypt.sh


  • ATTENZIONE: LA MACCHINA DA CUI SI ESEGUE LO SCRIPT DEVE AVERE ACCESSO AL DNS PRIMARIO DEL DOMINIO (PORTE TCP/UDP 53 APERT, ED AVERE ACCESSO LIBERO HTTP ED HTTP
  • Se si deve utilizzare un server proxy, dichiaralo in:
sudoedit -u letsencrypt.sh  /etc/letsencrypt.sh/.curlrc
proxy = proxy.example.priv:3128

Preparazione script update DNS

  • Copiare la chiave generata la punto precedente
sudo cp Kletsencrypt.myhost.example.priv.+157+60414.* /etc/letsencrypt.sh/
  • Creare lo script di update del recod TXT:
sudoedit /etc/letsencrypt.sh/hooks/hook-nsupdate.sh
#!/usr/bin/env bash

#
# Example how to deploy a DNS challange using nsupdate
#
. /etc/letsencrypt.sh/config

umask 077

updatefile="$(mktemp)"

NSUPDATE="nsupdate -v -k /etc/letsencrypt.sh/${DNS_KEY}"
done="no"

if [[ "$1" = "deploy_challenge" ]]; then
	echo "* Writing TXT Record:"
    printf "update add _acme-challenge.%s. 300 in TXT \"%s\"\n\n" "${2}" "${4}"
    printf "update add _acme-challenge.%s. 300 in TXT \"%s\"\n\n" "${2}" "${4}" > "${updatefile}"
    $NSUPDATE "${updatefile}"
    done="yes"
	#sudo rndc -k /etc/bind/rndc.key -s localhost freeze
	#sudo rndc -k /etc/bind/rndc.key -s localhost thaw
	#sudo /etc/init.d/bind9 reload
	echo "The challenge is ${4}"
	echo "The TXT record on primary DNS is:"
	host -t txt _acme-challenge.${2}. ${DNS_SERVER}
	#read -p "Please reload slave" P
	#echo "The TXT record on secondary DNS is:"
	#host -t txt _acme-challenge.${2}. dns2.rvmgroup.it
	#read -p "Press any key ..." P
fi

if [[ "$1" = "clean_challenge" ]]; then
	echo "* Deleting TXT Record"
    printf "update delete _acme-challenge.%s. 300 in TXT \"%s\"\n\n" "${2}" "${4}" > "${updatefile}"
    $NSUPDATE "${updatefile}"
	#sudo rndc -k /etc/bind/rndc.key -s localhost freeze
	#sudo rndc -k /etc/bind/rndc.key -s localhost thaw
	#sudo /etc/init.d/bind9 reload
    done="yes"
fi

if [[ "${1}" = "deploy_cert" ]]; then
    # do nothing for now
    done="yes"
fi

rm -f "${updatefile}"

if [[ ! "${done}" = "yes" ]]; then
    echo Unkown hook "${1}"
    exit 1
fi

exit 0
  • Renderlo eseguibile:
sudo chmod +x /etc/letsencrypt.sh/hooks/hook-nsupdate.sh

Installazione Client letsencrypt.sh

  • Installare le dipendenze:
sudo apt-get install ca-certificates git openssl curl
  • Installare l'eseguibile:
cd /tmp
git clone https://github.com/lukas2511/letsencrypt.sh.git
sudo cp letsencrypt.sh/letsencrypt.sh /usr/local/bin/


  • Modificare la configurazione:
cd /etc/letsencrypt.sh/
sudoedit config
CONFIG_D=/etc/letsencrypt.sh/config.d
BASEDIR=/etc/letsencrypt.sh
WELLKNOWN="/etc/letsencrypt.sh/.well-known/acme-challenge/"
CONTACT_EMAIL=admin@example.com
CHALLENGETYPE="dns-01"
DNS_KEY="Kletsencrypt.myhost.example.priv.+157+60414.private"
DNS_SERVER="dns1.example.com"
  • Creare il wrapper che sarà eseguito da cron per rinnovare i certificati:
sudoedit cron/letsencrypt.cron.sh
#!/bin/bash

cd /etc/letsencrypt.sh
/usr/local/bin/letsencrypt.sh --cron --challenge dns-01 --hook /etc/letsencrypt.sh/hooks/hook-nsupdate.sh
  • Renderlo eseguibile:
sudo chmod +x cron/letsencrypt.cron.sh
  • Sistemare i diritti dei files creati:
 sudo chown -R letsencrypt.sh  /etc/letsencrypt.sh

Configurazione richiesta certificati

  • Creare il file contenente i certificati da richiedere
cd /etc/letsencrypt.sh
sudoedit domains.txt
mail.example.com webmail.example.com

Test richiesta certificati

  • Testare:
sudo -u letsencrypt.sh /etc/letsencrypt.sh/cron/letsencrypt.cron.sh
  • Se tutto funziona, i certificati saranno in
/etc/letsencrypt.sh/certs/mail.example.com/
privkey.pem è la private key
fullchain.pem è il certificato concatenato con le CA
cert.pem è il certificato standalone

Impostazione Cron per il rinnovo automatico

  • Creare il file di cron
sudoedit /etc/cron.d/letsencrypt
01 11 * * * letsencrypt.sh /etc/letsencrypt.sh/cron/letsencrypt.cron.sh > /dev/null

Dichiarazione certificati per Apache

SSLCertificateKeyFile /etc/ssl/private/mail.example.com.key
SSLCertificateFile    /etc/ssl/certs/mail.example.com.crt
SSLCertificateChainFile /etc/ssl/certs/mail.example.com.crt

Dichiarazione certificati per Dovecot

sudoedit /etc/dovecot/conf.d/10-ssl.conf
ssl_cert = </etc/ssl/certs/mail.example.com.crt
ssl_key = </etc/ssl/private/mail.example.com.key

Dichiarazione certificati per Postfix

sudoedit /etc/postfix/main.cf
smtpd_tls_cert_file=/etc/ssl/certs/mail.example.com.crt
smtpd_tls_key_file=/etc/ssl/private/mail.example.com.key
smtpd_tls_CAfile = /etc/ssl/certs/letsencrypt.org.pem

Script di deploy dei certificati

  • Ora letsencrypt.sh provvederà rinnovare il certificato quando avrà meno di 30 giorni di validità. Dobbiamo implementare il meccanismo con cui i certificati vengono ricaricati in Apache al loro rinnovo
  • I certificati dovranno essere spostati nelle relative directory sotto /etc/ssl
  • Creiamo un altro script, che dovrà esere eseguito come root, che confronta i certificati in uso con quelli
sudoedit /etc/letsencrypt.sh/hooks/deploy.sh
#!/bin/bash
#
# MUST BE RUN AS ROOT
#
set -x
BASEDIR="/etc/letsencrypt.sh"
SSLDIR="/etc/ssl"

CERTS=$(/bin/ls -x ${BASEDIR}/certs/)

for CERT in $CERTS
do
	# Check if CA certificate has changed
  	if !(diff -q ${BASEDIR}/certs/${CERT}/chain.pem ${SSLDIR}/certs/letsencrypt.org.pem > /dev/null)
	then
		cp -L ${BASEDIR}/certs/${CERT}/chain.pem /usr/local/share/ca-certificates/letsencrypt.org.crt
		update-ca-certificates > /dev/null
	fi

	# Check if the certificate has changed
  	if !(diff -q ${BASEDIR}/certs/${CERT}/fullchain.pem ${SSLDIR}/certs/${CERT}.crt > /dev/null)
	then
		echo "Certificate for ${CERT} has been renewed."
		cp -L "${BASEDIR}/certs/${CERT}/privkey.pem"   "${SSLDIR}/private/${CERT}.key"
		cp -L "${BASEDIR}/certs/${CERT}/fullchain.pem" "${SSLDIR}/certs/${CERT}.crt"
		chmod 400 "${SSLDIR}/private/${CERT}.key"
		chmod 644 "${SSLDIR}/certs/${CERT}.crt"

		# Restart relevant services
		#  [[ "${jail}" = "http" ]] && jexec ${jail} service apache24 restart
	  	#[[ "${jail}" = "mail" ]] && jexec ${jail} service smtpd    restart
		/etc/init.d/apache2 restart > /dev/null
		/etc/init.d/postfix restart > /dev/null
		/etc/init.d/dovecot restart > /dev/null

		# Clean up old keys and certs
		sudo -u letsencrypt.sh /usr/local/bin/letsencrypt.sh --cleanup --hook /etc/letsencrypt.sh/hooks/hook-nsupdate.sh > /dev/null
	fi
done
  • Renderlo eseguibile, e testarlo: non deve fare nulla:
sudo chmod a+x /etc/letsencrypt.sh/hooks/deploy.sh
sudo /etc/letsencrypt.sh/hooks/deploy.sh
  • Impostarne l'esecuzione COME ROOT subito dopo il lancio di letsencrypt. Attenzione: viene usato sudo nello script:
sudoedit /etc/cron.d/letsencrypt
11 11 * * * root            /etc/letsencrypt.sh/hooks/deploy.sh

Riferimenti