Proyecto domótica PARTE 5 - Conexión segura mediante SSL

Hasta este punto ya deberíamos ser capaz de llegar a nuestro servidor por medio del dominio dinámico que hemos comprado y/o configurado.

El siguiente paso es generar un certificado SSL que permite realizar una conexión cifrada y segura para las conexiones que se realicen hacia el servidor a través de la web.

5.1 Instalación de Certbot

Certbot es un software que mediante un sistema de desafío permite validar la propiedad de tu dominio, generando los archivos de firma necesarios para levantar un servidor web seguro (HTTPS).

Existen dos formas de realizar este desafío, en forma automatizada (Certbot levanta un servidor web o utiliza uno existente, y coloca ciertos archivos que son usado como clave para validar la propiedad) y la otra opción es en forma manual (agregando a mano registros de DNS). Acá indicaremos ambas formas para lograr el desafío.

5.1.1 Agregar repositorio

sudo add-apt-repository ppa:certbot/certbot

Presionar enter para continuar con la instalación

5.1.2 Instalar la aplicación
Ejecutar el comando de instalación del gestor de paquetes de Ubuntu "apt".

sudo apt install certbot

La instalación descargará los archivos necesarios y notificará cuando esté lista

Modo simulación

Certbot por razones de seguridad solo permite realizar 5 ejecuciones en forma consecutiva, eso significa que por el motivo que sea si al quinto intento no logramos cumplir el desafío de forma exitosa Certbot rechazará los siguientes intentos, y deberemos esperar un lapso de tiempo entre 1 hora a 1 día completo, ya que dependerá de la carga de peticiones que tengan.

Para evitar este bloqueo de intentos, Certbot permite realizar una prueba simulada, eso significa que realiza una prueba real del desafío pero sin llamar a sus servidores, evitándonos perder tiempo en caso de fallas en nuestra infraestructura.

Para simular una generación o renovación de certificado simplemente hay que agregar el siguiente parámetro en los comandos:

--dry-run

Ejemplo:



Generar los archivos del certificado de la firma por medio de un desafío de registro de dominio (manual)

Certbot incluye un método automatizado de desafío donde  no se requiere interacción humana, lamentablemente en mi caso el router no me permitió cambiar la dirección del puerto 80 ya que por motivos de mantenimiento el proveedor de internet utiliza el puerto 80 para acceder al router y configurarlo, y justamente el puerto 80 es el utilizado para el desafío automatizado, por este motivo tuve que recurrir a la opción manual.

El siguiente comando de Certbot utiliza el método manual, para ello solo hay que agregar el dominio y seguir los siguientes pasos.

sudo certbot -d <nombre-del-dominio> --manual --preferred-challenges dns certonly

Cuando se ejecute el comando, Certbot quedará pausado e indicará las instrucciones para cumplir el desafío, en mi caso me solicitó agregar un registro de DNS en mi dominio.

Dado que solicitó un desafío de registro de DNS, se debe copiar el dato esperado para utilizarlo en el próximo paso.

Cumplir el desafío

Para cumplir el desafío se debe ingresar al sitio web del proveedor de dominio, yo al haberlo comprado en Google Domains en su sitio encontraré el formulario de registros de DNS.

Ingresar al dominio a configurar y en el menú DNS -> Registros de recursos personalizados.

En el formulario se debe ingresar la el nombre del registro, el tipo TXT y pegando el dato que copiamos en el punto anterior.


Considerando que la información de registros de DNS no es instantánea ya que debe propagarse por los distintos servidores de nombres, primero debemos verificar que la máquina ya posee acceso al registro. Para ello abrimos una nueva terminal en el servidor (ojo, no sirve que otro computador sea capaz de leerlo debe verificarse desde el servidor) y ejecutamos el siguiente comando.

dig -t txt <registro-del-desafio>

Si somos capaces de ver el dato que se muestra entre "", y si además coincide con el que agregamos en el registro de DNS del dominio, significa que podemos continuar con el desafío:



Volvemos a la terminal que tiene pendiente el desafío de Certbot y presionamos la tecla "Enter" para continuar:



Al continuar con el desafío, si la verificación del registro de DNS coincide correctamente generará los archivos de firma del certificado SSL. En los siguientes capítulos explicaré como utilizarlos en un servidor HTTPS.

Renovación automática del certificado por medio de crontab

Dado que el certificado tiene una fecha de espiración, podemos crear una estrategia que lo renueve de forma automática, y de esta forma ahorrarnos el proceso manual del desafío, esto solo podrá funcionar si Certbot puede levantar su propio servidor, de no ser así tendremos que realizarlo en forma manual una vez este caduque.

Abrir Crontab:
EDITOR=nano crontab -e

Agregar la siguiente linea a Crontab:
18 4 * * * certbot renew

Ejemplo de mi Crontab:


Generar los archivos del certificado de la firma en forma automática

Certbot standalone

La forma más sencilla de actualizar el certificado es que Certbot levante su propio servidor web y valide el desafío, para ello ejecutamos el siguiente comando:

sudo certbot certonly --standalone -d <nombre-del-dominio> 

Certbot webroot

La segunda forma automatizada es utilizar un servidor web existente, debido a configuraciones especificas o de seguridad nuestro puerto 80 podría estar ocupado por otro servicio, o simplemente des-habilitado siendo dirigido mediante un servidor proxy, para ello necesitamos que el servidor a reutilizar permita exponer públicamente un directorio estático:

El siguiente comando copiará en nuestro servidor web los archivos del desafío el directorio público que especifiquemos:

sudo certbot certonly --webroot -d <nombre-del-dominio> 


Una vez ejecutado, nos solicitará la ruta del directorio estático de nuestro servidor web, en el caso de este proyecto, deberá dejarlo en el directorio "./build/esm-bundled"
 

Luego de generar el certificado, Certbot nos indica las rutas donde han quedado lo archivos de nuestro certificado, el cual ya podemos agregar a nuestro servidor web para cumplir con la normativa y servir nuestro sitio web a través de HTTPS.

Ruta de los certificados recién generados

La ruta de los certificados recién generados puede variar dependiendo de el método usado pero la ruta probable es:

/etc/letsencrypt/live/<nombre-del-dominio>

Dado que el propietario de los certificados será el super usuario, es necesario cambiar el propietario del directorio, de esta forma poder acceder a los archivos recién generados, ejecute el siguiente comando:

sudo chown <usuario-del-servidor> -R /etc/letsencrypt

Hooks y renovación automática del certificado por medio del propio Certbot

Luego de generar los certificados en forma automatizada, Certbot creará automáticamente un programa de renovación con los parámetros necesarios para volver a generar archivos de certificados y reemplazar los caducados.

Una vez Certbot genere correctamente los nuevos archivos, será necesario reiniciar el servidor web SSL para que el servidor y los clientes puedan utilizar el certificado recién renovado.

Los hooks permiten ejecutar comandos durante el ciclo de vida de la renovación de certificado, para ello podemos especificar comandos dentro de los eventos "deploy", "pre" y "post" ejecución de Certbot.

En el caso de este proyecto, el servidor web correrá com un servicio en segundo plano por lo tanto agregando una orden de reinicio del servicio bastará para que el servidor web exponga el nuevo certificado SSL.

sudo sh -c 'printf "#!/bin/sh\nservice mysmarthome restart\n" > /etc/letsencrypt/renewal-hooks/post/mysmarthome.sh'
sudo chmod 755 /etc/letsencrypt/renewal-hooks/post/mysmarthome.sh




Posible error de renovación

Un posible fallo al intentar renovar el certificado puede deberse a que el archivo de configuración haya quedado incompleto.



Para solucionar este error es necesario agregar unas propiedades extras en el archivo de configuración, por ello es necesario abrir el archivo de configuración en el editor:

sudo nano /etc/letsencrypt/renewal/<nombre-del-dominio>.conf

Agregar las siguientes lineas al final del archivo, indicando la ruta del directorio público estático del servidor web:

webroot_path = /opt/smart-home-advanced/build/esm-bundled
[[webroot_map]]
norseacademy.org = /opt/smart-home-advanced/build/esm-bundled

Quedando:



Luego al volver simular la renovación, esta se ejecuta correctamente:




Comentarios