Gracias a la inciativa https://letsencrypt.org/ respaldado por Akamai, Cisco, Mozilla and EFF, vamos a poder disponer de certificados SSL gratuitos. En este post os explicare como he automatizado el proceso de generación y renovación en un servidor Debian, con diversos virtualhost, modificando lo menos posible y de una manera muy controlada los ficheros de configuración de apache.
La intención del proyecto LETSENCRYPT es extender al máximo la utilización de certificados SSL, para ello los propios servidores podran autogenerar sus certificados sin interacción manual, para forzar que todo sea automatico, los certificados tendran 90 dias de validez, obligandonos a todos los administradores de sistemas a automatizar el proceso.
Para generar un certicado, la Autoridad de Certificación de Let’s Encrypt, consulta el DNS y accede a tu servidor web preguntandole por unas credenciales para de esta manera validar la generación o renovación del certificado.
Por lo tanto el servidor web debe de responder a las consultas realizadas por CA, para la emisión y renovación de los certificados. El software de letsencrypt es capaz de modificar los ficheros de configuración de apache, o incluso levantar un servidor propio. Ninguno de los dos metodos me convencen, quiero tener pleno control de todas las modificaciones en la configuración de apache, dispongo de diversidad de virtualhost con configuraciones muy especificas, el levantar un servidor independiente hace que dejes de dar servicio por lo que tampoco es aceptable. Afortunadamente Letsencrypt proporciona un mecanismo denominado webroot, por el cual lo unico que necesita es dejar un fichero en algun lgugar accesible del website, con este modo podemos automatizar plenamente el proceso y mantener pleno control sobre lo que esdta sucediendo.
Lo primero de todos es seguir la instrucciones de instalación de letsencrypt (Probado en Debian jessie y Debian Wheezy)
apt-get install git
git clone https://github.com/letsencrypt/letsencrypt
cd letsencrypt
./letsencrypt-auto
Vamos allá, la única modificación necesaria en cada virtualhost para poder responder a la autenticación de Let’s encrypt es:
Alias /.well-known /var/www/html/le/.well-known
Reiniciamos el apache, y ya podemos lanzar el comando para la emisión y renovación del certificado.
/root/.local/share/letsencrypt/bin/letsencrypt --renew-by-default -a webroot --webroot-path /var/www/html/le/ --server https://acme-v01.api.letsencrypt.org/directory --email admin@damia.net --text --agree-tos --agree-dev-preview -d eblog.damia.net auth
Con esto ya tenemos los certificados listos:
/etc/letsencrypt/live/eblog.damia.net/cert.pem
/etc/letsencrypt/live/eblog.damia.net/chain.pem
/etc/letsencrypt/live/eblog.damia.net/fullchain.pem
/etc/letsencrypt/live/eblog.damia.net/privkey.pem
Podemos añadir otro virtualhost en el puerto 443, con:
[...]
SSLEngine on
SSLCertificateFile /etc/letsencrypt/live/eblog.damia.net/cert.pem
SSLCertificateKeyFile /etc/letsencrypt/live/eblog.damia.net/privkey.pem
SSLCertificateChainFile /etc/letsencrypt/live/eblog.damia.net/fullchain.pem
[...]
Hecho, ya tenemos nuestra web segura.
Ahora podemos automatizar el proceso de creación y renovación de certificados, He desarrollado un script que realiza las siguiente tareas:
- Comprueba la fecha de expiración de los certificados y los renueva cuando estan por debajo de un numero de dias definido.
- Comprueba que letsencrypt puede acceder al directorio de validación
- Envia un correo al administrador si no puede renovar lso certificados.
Puedes ver el codigo a continuación o descargarte el fichero desde aqui: autole
#!/bin/bash
##
##
## LETS ENCRYPT AUTOMATION
##
## by Damia Soler
## Contact damia (at) damia (dot) net
## https://blog.damia.net
## https://github.com/damiadev/autole/
##
##
##==================================================
## SETUP
##
##
##
## REMAINING DAYS TO EXPIRE BEFORE RENEW
##
DAYSTORENEW=10
##
## REMAINING DAYS TO EXPIRE BEFORE ALERT
##
DAYSTOALERT=5
##
## EMAIL TO ALERT IF UNABLE TO RENEW
##
ALERTEMAIL=root@localhost
##
## EMAIL ACCOUNT ON LETS ENCRYPT
##
LEEMAIL=admin@example.com
##
WEBROOT=/www/htdocs/le/
##WEBROOT=/www/htdocs/le/$1
##
##
LEBIN=/root/.local/share/letsencrypt/bin/letsencrypt
##
CERTFILE=/etc/letsencrypt/live/$1/cert.pem
##====================================================================================
if test $1 = "--renew-all" ; then
echo Checking certificates
ls -1 /etc/letsencrypt/live|xargs -n1 $0 ;
/etc/init.d/apache2 graceful
exit ;
fi;
##====================================================================================
if test -a $CERTFILE ; then
d1=$(date -d "`openssl x509 -in $CERTFILE -text -noout|grep "Not After"|cut -c 25-`" +%s)
d2=$(date -d "now" +%s)
DAYS=` echo \( $d1 - $d2 \) / 86400 |bc `
echo -n `date` DOMAIN $1 will expire in $DAYS days " "
else
echo -n `date` DOMAIN $1 new
DAYS=$DAYSTOALERT;
fi;
if test $DAYS -lt $DAYSTORENEW ; then
echo Trying to renew ;
### PRETEST TO NOT MESS LE SERVERS IF YOU ARE NOT ANSWERING THE CHALLENGE
TESTFILE=$RANDOM
echo test> $WEBROOT/.well-known/acme-challenge/$TESTFILE
URL=http://$1/.well-known/acme-challenge/$TESTFILE
mkdir -p $WEBROOT/.well-known/acme-challenge
touch $WEBROOT/.well-known/acme-challenge/index.html
echo test> $WEBROOT/.well-known/acme-challenge/$TESTFILE
if curl --output /dev/null --silent --head --fail "$URL"; then
echo $LEBIN --renew-by-default -a webroot --webroot-path $WEBROOT --email $LEEMAIL --text --agree-tos -d $1 auth
$LEBIN --renew-by-default -a webroot --webroot-path $WEBROOT --email $LEEMAIL --text --agree-tos -d $1 auth
echo SSLEngine on
echo SSLCertificateFile /etc/letsencrypt/live/$1/cert.pem
echo SSLCertificateKeyFile /etc/letsencrypt/live/$1/privkey.pem
echo SSLCertificateChainFile /etc/letsencrypt/live/$1/fullchain.pem
else
echo "CAN NOT ACCESS THE PRE-CHALLENGE $URL PLEASE ADD ALIAS TO YOUR VIRTUALHOST CONF" ;
echo "Alias /.well-known $WEBROOT/.well-known" ;
fi
rm $WEBROOT/.well-known/acme-challenge/$TESTFILE
else
echo no close to expire ;
fi ;
if test $DAYS -lt $DAYSTOALERT ; then
echo ALERT DOMAIN $1 CERTIFICATE RENEWAL PROBLEM|mail $ALERTEMAIL ;
echo ALERT DOMAIN $1 CERTIFICATE RENEWAL PROBLEM ;
fi;
You can use
./autole www.mydomain.com
And you will have your new certificate available for this domain. (remeber to add previously the alias on apache).
And
./autole --renew-all
And all your certificates will be renewed. The idea is to add this to the crontab, and your certificates will be ready and renew automatically.
AVISO: A día de hoy con Debian 9 “stretch” ya no es necesario hacer este hack, el paquete dehydrated que viene en la propia distribución hace todo el trabajo de manera similar.