Usando letsencrypt.sh para crear y renovar certificados

La naturaleza abierta del proyecto Let’s Encrypt permite que existan  clientes alternativos al oficial. Yo me he decidido por uno escrito en Bash por Lukas Schauer, muy ligero y fácilmente trazable. Bueno, lo de fácilmente es un decir porque cuando se llega a la parte de openssl las cosas se complican un poco con tanto parámetro y tanto condicionante; el resto se comprende de un vistazo rápido.

El caso es que funciona muy bien y los resultados son fácilmente aplicables a los servicios del sistema como detallaré más abajo. De momento éstos son los pasos que he seguido:

  1. Descargar el programa
  2. Crear la configuración
  3. Activar (y verificar) el protocolo ACME challenge.
  4. Acomodar el programa en el sistema.

Descarga del programa

Tan simple como clonar el repositorio en algún lugar que no estorbe. En mi caso he empleado el directorio de trabajo de la cuenta que uso para configurar el servidor y luego lo he lanzado con privilegios de administración cuando lo he necesitado (que es más bien siempre).

Crear la configuración

El programa emplea como valor predeterminado para la configuración y los certificados la ruta

/etc/letsencrypt.sh

y me ha parecido muy bien, aunque se puede cambiar utilizando el parámetro

--config

. He creado el directorio y he situado allí dos archivos: uno para definir los dominios para los que quiero un certificado digital y otro para algunos ajustes en la configuración que me faciliten la automatización de la renovación.

El archivo

/etc/letsencrypt.sh/domains.txt

contiene en líneas aparte los dominios para los que queremos certificados separados por espacios en blanco. El primero es el dominio principal y los restantes son los nombres alternativos para el mismo.

taquiones.net mail.taquiones.net db.taquiones.net
astillas.net git.astillas.net 
vm69.net

Respecto a la configuración he añadido lo siguiente en

/etc/letsencrypt.sh/config.sh

(es un archivo shell):

# Archivo de configuración de openssl
OPENSSL_CNF=/usr/lib/ssl/openssl.cnf

# Ruta al directorio del protocolo ACME
WELLKNOWN=/var/www/letsencrypt

# Dirección de contacto
CONTACT_EMAIL=victor@example.net

Para crear los archivos CSR (Certificate Signing Request) con openssl es imprescindible que exista su archivo de configuración. Al parecer el mío había desaparecido del sistema y me he limitado a copiar una versión ejemplo que he encontrado por ahí y la he situado en

/etc/ssl/openssl.cnf

ya que Debian mantiene un enlace simbólico desde

/usr/lib/ssl/openssl.cnf

hacía allí; supongo que porque se trata de un archivo de configuración y la normativa Debian indica que deben estar bajo

/etc

.

Acomodar el programa en el sistema

Fase que incluye el probarlo por vez primera. Una vez que nos hemos asegurado de que respondemos correctamente al reto del protocolo ACME ejecutamos el programa con el parámetro

--cron

para obtener nuestros certificados.

Si todo ha ido bien los habrá creado bajo su directorio de configuración concretamente en bajo el subdirectorio certs:

.
├── certs
│   ├── astillas.net
|   .
|   .
│   ├── taquiones.net
|   .
|   .
|   └── vm69.net

En cada uno de ellos tendremos enlaces simbólicos apuntando a la última versión de cada componente que necesitamos:

  • cert.pem: es el certificado del servidor.
  • chain.perm: son los certificados intermedios.
  • fullchain.pem: el certificado del servidor y los intermedios.
  • privkey.pem: es la clave privada de lo anterior.

Después sólo resta instalar el programa y crear una tarea de renovación en el sistema:

$ sudo install -o root -g root -m 0555 letsencrypt.sh /usr/local/bin
$ cat <<EOF > renew.cron
# Renovación semanal en domingo
0 23 * * 0 root /usr/local/bin/letsencrypt.sh --cron
EOF
$ sudo install renew.cron /etc/cron.d/letsencrypt

Renovando certificados

El programa letsencrypt.sh, al igual que los demás que he visto, comprueban que la validez del certificado sea superior a los treinta días y si no es así solicitan renovarlo. También ocurre cuando la lista de dominios ha sufrido alguna alteración como el añadido o el borrado de algún nombre.

Luego está la cuestión de que tras la renovación los certificados han cambiado y nos encontramos con el problema de reiniciar aquellos servicios que hacen uso de ellos.

El programa letsencrypt.sh permite llamar a una función con el nombre de

deploy_cert()

que debe incluirse dentro del fuente principal en el archivo

hook.sh

del directorio de configuración.

Un ejemplo:

function deploy_cert
{
        local DOMAIN="${1}" KEYFILE="${2}" CERTFILE="${3}" FULLCHAINFILE="${4}" CHAINFILE="${5}"

        # En cualquier caso reiniciar el servidor web
        echo "Reiniciando servidor web ..." >&2
        systemctl restart apache2

        # y luego según el caso afinamos más
        case $DOMAIN in
        taquiones.net) 
                # Reiniciar servidores de correo, mensajería 
                echo "Reiniciando servidores de correo y mensajería ..." >&2
                systemctl restart qpsmtpd
                systemctl restart dovecot
                systemctl restart prosody
                ;;
        esac
}

 

Servidor de correo electrónico en Debian

Aunque el servidor no vaya a gestionar buzones de correo electrónico considero que es valioso que sea capaz de enviar y recibir mensajes sin necesitar una pasarela con sus credenciales.

Esto es especialmente cierto ya que suelo centralizar la cuenta del administrador para todas mis máquinas en una cuenta externa, y me gusta que no tengan problemas a la hora de enviarme avisos. Es un rollo tener que consultar varios buzones locales para saber qué ha ocurrido.

Así pues, quiero que cada máquina pueda enviar correo al exterior y necesito reducir las posibilidades de que le ignoren (marcándolo como spam) o directamente le denieguen el acceso.

Para ello el servidor tiene que cumplir una serie de requisitos:

  1. Registros MX apuntando al nombre completo del servidor.
  2. Dirección IP apuntando a nombre completo del servidor (resolución inversa).
  3. SPF activo en el registro DNS (también importante si se emplean Google Apps).
  4. DKIM activo en el servidor de correo (exim) y en el DNS.
  5. DMARK rematando ambos mecanismo ya que presentan algún fleco por el que podrían ser inutilizados.

Steve Kemp tiene varios artículos al respecto. Como resumen podemos afirmar que todos requieren cambios en el DNS y la implicación del servicio de correo.

SPF

Ya hay excelentes explicaciones de cómo funciona el invento así que no me voy a extender en ello. Si escribo ésto es para anotar detalles técnicos a los que tendré que recurrir una y otra vez en el futuro.

  1. Crear un registro de texto en el DNS de mi dominio indicando qué máquinas están autorizadas a enviar correo desde él.
  2. Indicar al servidor de correo (exim4) que emplee la verificación SPF cuando reciba correo.

En este dominio el registro SPF queda así:

v=spf1 mx a ip4:46.101.91.82/32 -all

donde indico que sólo los servidores definidos en el registro MX pueden enviar correo en su nombre, concretamente señalo la dirección IP, e indico que los correos tienen que rechazarse si no cumplen alguna de éstas condiciones (-all). Se puede consultar la síntaxis aquí.

Una vez tengamos la definición es recomendable crear dos registro en el DNS del dominio: uno de tipo SPF y otro de tipo TXT. Por lo visto no todos los clientes consultan el primero y es algo que no cuesta.

Respecto a exim4 sólo tenemos que preocuparnos de la recepción del correo y para ello vamos a indicar que emplee SPF

  1. Asegurarnos de tener instalada la versión exim4-daemon-heavy.
  2. Instalar el paquete spf-tools-perl.
  3. Activar la comprobación vía CHECK_RCPT_SPF=true en el archivo /etc/exim4/conf/main/00_local_macros y reiniciar.

Si el registro SPF hubiese contenido una política de fallo blando (~all)los mensajes recibidos serían aceptados pero se incluiría un aviso en forma de cabecera especial

Received-SPF: softfail client-ip=...

que podría ser utilizada por posteriores filtros de spam. En este caso concreto prefiero que dichos correos sean rechazados durante la conexión (parámetro -all) como el fragmento de conexión que muestro a continuación:

MAIL FROM:<root@esferas.org>
250 OK
RCPT TO:<root@esferas.org>
** 550-[SPF] 79.148.243.240 is not allowed to send mail from esferas.org. Please
** 550 see http://www.openspf.org/Why?scope=mfrom;identity=root@esferas.org;ip=79.148.243.240

DKIM

Este mecanismo consiste en emplear un par de claves criptográficas, una pública y otra privada, y publicar la primera, la pública, en el registro DNS. El servidor de correo firmará con la clave privada los mensajes salientes y el receptor del mismo podrá, tras consultar el registro DNS correspondiente, verificar la autenticidad del mismo.

Los pasos a seguir son los siguientes:

  1. Crear un par de claves criptográficas empleando openssh. La única precaución a tomar es la longitud de la clave. Proveedores como gandi.net no admiten más de 1024 bits.
  2. Elegir una palabra clave como selector dado que en un mismo dominio pueden coexistir varios registros TXT. Este selector tendrá que incluirse en el DNS y en el servidor de correo que emplea el mecanismo.

Enlaces y referencias