En este artículo veremos detalladamente cómo agregar encriptación en nuestras comunicaciones MQTT.
Si todavía no has visto cómo instalar un servidor MQTT en una Raspberry Pi, te invito a leer este artículo.
Qué es TLS/SSL y para qué sirve
Para empezar, TLS es un estándar basado en SSL, que apareció luego que se descubrieran las vulnerabilidades del SSLv3. Así que cuando hablamos de SSL, hoy generalmente nos estamos refiriendo a TLS.
El propósito de utilizar SSL/TLS es brindar autenticación, encriptación e integridad.
Esto quiere decir lo siguiente:
- Autenticación: Quien envía el mensaje es quien dice ser.
- Encriptación: Nadie en el camino puede leer el mensaje.
- Integridad: El mensaje no puede ser modificado.
Para lograr esto se utiliza una firma digital (certificado) y llaves públicas y privadas para encriptar y desencriptar el mensaje. A continuación veremos, paso a paso, cómo agregar encriptación a la comunicación con MQTT.
Pasos a seguir
- Crear una clave pública y una privada para la autoridad de certificación (CA).
- Crear un certificado para la CA y firmarlo con la clave privada antes generada.
- Generar una clave pública y una privada para el broker MQTT.
- Crear un requerimiento de firma de certificado para las claves del paso anterior.
- Utilizar el certificado del paso 2 para firmar el requerimiento del paso anterior.
- Copiar todos los certificados en un directorio del broker MQTT.
- Copiar el certificado de la CA en el cliente.
- Editar la configuración de Mosquitto.
- Editar la configuración del cliente para que utilice TLS y el certificado de la CA.
Todo esto parece bastante complicado, pero vamos a ir paso a paso. Primero instalemos ssl en nuestra Raspberry Pi mediante el siguiente comando.
sudo apt-get install openssl
1.- Crear el par de claves para la CA
Ejecutamos el siguiente comando en la Raspberry. Notar que utilizamos la opción sudo para ejecutar el comando con permisos de root.
sudo openssl genrsa -des3 -out ca.key 2048

Al ejecutar el comando se generará el certificado y se solicitará una frase clave.
2.- Crear un certificado para la CA y firmarlo
Ejecutamos el siguiente comando. Al hacerlo, se nos pedirá la frase clave que ingresamos en el punto anterior y luego una serie de datos. El más importante es el Common Name, que puede ser un nombre cualquiera. En el caso de los sitios web, se utiliza el nombre de dominio del sitio (www.sitioweb.com, sitioweb.com). En nuestro caso podemos elegir cualquier nombre, yo he utilizado el nombre de host (raspberry). Recordemos que debemos poder resolver el nombre de nuestra Raspberry.
También podemos usar la dirección IP si no deseamos usar un nombre.
openssl req -new -x509 -days 1826 -key ca.key -out ca.crt

3.- Crear un par de claves para el broker MQTT
En este paso crearemos el par de claves para el broker, mediante el siguiente comando:
sudo openssl genrsa -out server.key 2048

4.- Crear un certificate request
Ahora crearemos un archivo de requerimiento de certificado (.csr). Durante la creación se pedirán los mismos valores que para el certificado de autoridad (CA) y valen los mismos comentarios. Sin embargo, se debe cambiar alguno de estos valores para que no queden exactamente igual en ambos certificados, ya que esto hará que no funcione la conexión. En mi caso, he omitido ingresar el parámetro «City».
sudo openssl req -new -out server.csr -key server.key

5.- Firmar el requerimiento del certificado
En este paso utilizaremos el certificado CA para firmar el requerimiento que hicimos en el paso anterior. Este procedimiento creará el archivo .crt para el broker. El comando es el siguiente.
sudo openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out server.crt -days 360
Nuevamente se nos solicitará la frase clave que generamos al principio

6.- Ver archivos creados
Utilizando el comando ls vemos todos los archivos que hemos creado. El archivo ca.key no lo copiaremos al broker ni al cliente, ya que solo se utiliza para generar nuevos certificados.

7.- Copiar archivos al broker
Ahora copiamos los archivos ca.crt, server.crt y server.key en los directorios de configuración de Mosquitto.
Estos directorios están en /etc/mosquitto. En ca_certificates copiamos el archivo ca.crt y en certs los archivos server.crt y server.key.

8.- Copiar los certificados en el cliente
Ahora copiamos el archivo ca.crt en nuestro cliente. El lugar exacto obviamente variará en función de dónde tengamos el cliente. En mi caso utilizaré el cliente desarrollado por HiveMQ, que dicho sea de paso tienen mucha documentación sobre MQTT (en inglés). En esta página te puedes bajar el cliente para tu sistema operativo.
9.- Configurar Mosquitto
Debemos modificar la configuración de Mosquitto para que utilice SSL/TLS.
Mosquitto viene con un archivo de configuración de ejemplo, que se encuentra en el directorio /usr/share/doc/mosquitto/examples. Este archivo puede llamarse mosquitto.conf o mosquito.conf.example. En cualquier caso lo copiamos al directorio /etc/mosquitto/conf.d y le cambiamos el nombre a mosquitto.conf si tiene el sufijo .example.
sudo cp /usr/share/doc/mosquitto/examples/mosquitto.conf.example /etc/mosquitto/conf.d/mosquitto.conf
Una vez copiado lo editamos con
sudo nano /etc/mosquitto/conf.d/mosquitto.conf
Lo primero que hacemos es configurar el puerto en 8883, que es el que se utiliza para comunicaciones encriptadas.

Luego indicamos dónde están los archivos de certificados.

Luego hacemos
sudo service mosquitto restart
Y podemos verificar que el broker se inició corriendo el siguiente comando

10.- Probar la conexión con el broker
Finalmente toca probar la conexión con el broker desde el cliente que vamos a utilizar. Para hacerlo vamos a usar el nombre de host, así que primero debemos editar nuestro archivo hosts (si estamos en Windows) o el que corresponda según nuestro sistema operativo.

Si ahora hacemos un ping al host raspberry, nos debe responder nuestra Raspberry

Ahora vamos a abrir dos ventanas de comandos en Windows para correr dos clientes, uno publicando y otro suscribiendo. Los comandos son los siguientes. Es necesario primero correr el de la suscripción, así ve el mensaje que enviamos al publicar.
Para suscbribir
mqtt-cli.exe sub -t test -h raspberry -p 8883 -s –cafile ca.crt -V 3 -v
Para publicar
mqtt-cli.exe pub -t test -m «hola» -h raspberry -p 8883 -s –cafile ca.crt -V 3 -v


Algunas notas sobre las opciones de publicación y suscripción
sub | opción para suscribir |
pub | opción para publicar |
-t | tópico al que suscribirse o publicar |
-h | nombre del host |
-p | puerto del broker |
-s | con seguridad habilitada |
-m | mensaje a publicar |
–cafile | archivo de certificado |
-V | versión de MQTT, en este caso se debe usar la 3 |
-v | modo verboso |
Resumen
En este artículo hemos visto cómo agregar encriptación a nuestras comunicaciones con MQTT. Los pasos son varios, pero el procedimiento en sí no es complicado. Cuéntame en los comentarios qué te ha parecido este artículo y si tienes alguna duda.
Nos vemos en el siguiente artículo ;).
Referencias
Mosquitto SSL Configuration -MQTT TLS Security
Enable Secure Communication with TLS and the Mosquitto Broker
2 comentarios
Cómo instalar MQTT en Raspberry Pi - Tu fuente experta en IoT · 23 junio, 2020 a las 10:28 AM
[…] es la mejor opción en cada caso. Y si deseas agregar encriptación a la comunicación, mira este artículo donde explico cómo […]
MQTT vs HTTP - Qué elegir para tu proyecto IoT - Tu fuente experta en IoT · 7 agosto, 2020 a las 10:28 AM
[…] aquí tienes un artículo sobre cómo instalar un servidor MQTT en una Raspberry Pi. Y en este otro explico cómo agregar […]