Cómo Instalar y Asegurar el Broker de Mensajería MQTT Mosquitto en Ubuntu 20.04
Mosquitto es un broker de mensajes de código abierto que utiliza el Protocolo de Transporte de Telemetría de Colas de Mensajes (MQTT). El protocolo está diseñado para proporcionar una comunicación ligera a los dispositivos del Internet de las Cosas (IoT). Se utiliza habitualmente para el seguimiento GPS de vehículos, domótica, sensores medioambientales y recogida de datos a gran escala.
El protocolo MQTT se ejecuta sobre el modelo TCP/IP. Al ser ligero, su pequeña huella de código te permite crear aplicaciones para dispositivos con recursos mínimos. Se basa en el modelo publicar/suscribir. En este modelo, el cliente se conecta al servidor Mosquitto, que actúa como intermediario para enviar información a otros clientes suscritos a un canal.
En este tutorial, instalarás Mosquitto y configurarás el broker para que utilice SSL para proteger las comunicaciones.
Requisitos previos
- Un servidor Ubuntu 20.04 con un usuario no root con privilegios sudo.
- Un nombre de dominio (
myqtt.example.com
) apuntando a tu servidor.
Paso 1 – Instalar el Servidor y el Cliente Mosquitto
Ubuntu incluye la versión antigua 1.6 de Mosquitto. Para instalar la última versión, añade el repositorio oficial de Mosquitto.
$ sudo add-apt-repository ppa:mosquitto-dev/mosquitto-ppa
Instala el servidor y el cliente de Mosquitto.
$ sudo apt install mosquitto mosquitto-clients
Comprueba el estado del servidor.
$ sudo systemctl status mosquitto ? mosquitto.service - Mosquitto MQTT Broker Loaded: loaded (/lib/systemd/system/mosquitto.service; enabled; vendor preset: enabled) Active: active (running) since Tue 2022-01-25 09:18:40 UTC; 25s ago Docs: man:mosquitto.conf(5) man:mosquitto(8) Main PID: 119694 (mosquitto) Tasks: 1 (limit: 2274) Memory: 1.0M CGroup: /system.slice/mosquitto.service ??119694 /usr/sbin/mosquitto -c /etc/mosquitto/mosquitto.conf Jan 25 09:18:39 <userid> systemd[1]: Starting Mosquitto MQTT Broker... Jan 25 09:18:40 <userid> systemd[1]: Started Mosquitto MQTT Broker.
Paso 2 – Configurar la autenticación por contraseña MQTT
Mosquitto incluye una utilidad para generar un archivo de contraseñas llamado mosquitto_passwd
. Mosquitto almacena todas las configuraciones en el directorio /etc/mosquitto
.
Ejecuta el siguiente comando para generar un archivo de contraseña encriptado en /etc/mosquitto/passwd
para el nombre de usuario username
. Introduce una contraseña de tu elección.
$ sudo mosquitto_passwd -c /etc/mosquitto/passwd username Password: Reenter password:
A continuación, crea un archivo default.conf
en el directorio /etc/mosquitto/conf.d
y ábrelo para editarlo.
$ sudo nano /etc/mosquitto/conf.d/default.conf
Pega las siguientes líneas para especificar la ubicación del archivo de contraseña. Si omites el campo del oyente, siempre se conectará de forma anónima, independientemente de la configuración.
listener 1883 password_file /etc/mosquitto/passwd
Guarda el archivo pulsando Ctrl + X e introduciendo Y cuando se te solicite.
Reinicia el servidor Mosquitto para aplicar el cambio.
$ sudo systemctl restart mosquitto
Paso 3 – Probar el Cliente Mosquitto
Dependiendo del caso de uso, puedes utilizar el cliente Mosquitto para enviar y recibir mensajes sobre diferentes temas. Un cliente es un suscriptor o un publicador.
El siguiente paso es suscribirse a un tema. En el protocolo MQTT, un tema se refiere a una cadena utilizada por el servidor/corredor para filtrar mensajes para los clientes conectados. Aquí tienes algunos ejemplos de temas que puedes utilizar en una aplicación domótica.
- casa/luces/sala de estar
- casa/luces/cocina
- casa/luces/dormitorio_principal
- casa/luces/dormitorio_niños
Para suscribirte a un tema, ejecuta el comando mosquitto_sub -t
seguido del tema. Por ejemplo, para suscribirte al tema home/lights/kitchen
, ejecuta el siguiente comando.
$ mosquitto_sub -u username -P YOUR_PASSWORD -t "home/lights/kitchen"
No cierres la ventana existente. Abre una nueva ventana de terminal para publicar un mensaje en el tema home/lights/kitchen
utilizando el siguiente comando.
$ mosquitto_pub -u username -P YOUR_PASSWORD -m "ON" -t "home/lights/kitchen"
Vuelve a la primera ventana de terminal y recibirás el mensaje ON
.
ON
A continuación, envía el mensaje OFF
sobre el mismo tema desde el segundo terminal.
$ mosquitto_pub -u username -P YOUR_PASSWORD -m "OFF" -t "home/lights/kitchen"
El primer terminal mostrará el mensaje recién publicado.
ON OFF
Si intentas enviar un comentario no autenticado, fallará. Por ejemplo, prueba el siguiente comando.
$ mosquitto_sub -t "home/lights/sitting_room" Connection error: Connection Refused: not authorised.
No es recomendable, pero debes añadir la siguiente línea al archivo /etc/mosquitto/conf.d/default.conf
si quieres ejecutar los comandos sin autenticación.
allow_anonymous true
Paso 4 – Instalar SSL
Para instalar un certificado SSL utilizando Let’s Encrypt, necesitamos descargar la herramienta Certbot. Para ello utilizaremos el instalador de paquetes Snapd.
Instala el instalador Snap.
$ sudo apt install snapd
Asegúrate de que tu versión de Snapd está actualizada.
$ sudo snap install core $ sudo snap refresh core
Instala Certbot.
$ sudo snap install --classic certbot
Utiliza el siguiente comando para asegurarte de que se ejecuta el comando Certbot creando un enlace simbólico al directorio /usr/bin
.
$ sudo ln -s /snap/bin/certbot /usr/bin/certbot
Genera un certificado SSL.
$ sudo certbot certonly --standalone --agree-tos --no-eff-email --staple-ocsp --preferred-challenges http -m [email protected] -d mqtt.example.com
El comando anterior descargará un certificado en el directorio /etc/letsencrypt/live/mqtt.example.com
de tu servidor.
Genera un certificado de grupo Diffie-Hellman.
$ sudo openssl dhparam -out /etc/ssl/certs/dhparam.pem 2048
Crea un directorio raíz web de desafío para la renovación automática de Let’s Encrypt.
$ sudo mkdir -p /var/lib/letsencrypt
Crea un Cron Job para renovar el SSL. Se ejecutará cada día para comprobar el certificado y renovarlo si es necesario. Para ello, primero, crea el archivo /etc/cron.daily/certbot-renew
y ábrelo para editarlo.
$ sudo nano /etc/cron.daily/certbot-renew
Pega el siguiente código.
#!/bin/sh certbot renew --cert-name mqtt.example.com --webroot -w /var/lib/letsencrypt/
Guarda el archivo pulsando Ctrl + X e introduciendo Y cuando te lo pida.
Cambia los permisos del archivo de la tarea para que sea ejecutable.
$ sudo chmod +x /etc/cron.daily/certbot-renew
Paso 5 – Configurar MQTT SSL
Ahora que ya tenemos listos los certificados SSL, tenemos que proporcionar a Mosquitto acceso a ellos. Para ello, tenemos que copiar los certificados a una ubicación desde la que Mosquitto pueda acceder a ellos.
$ sudo cp /etc/letsencrypt/live/mqtt.example.com/fullchain.pem /etc/mosquitto/certs/server.pem $ sudo cp /etc/letsencrypt/live/mqtt.example.com/privkey.pem /etc/mosquitto/certs/server.key
Cambia la propiedad del directorio /etc/mosquitto/certs
al usuario mosquitto
creado durante la instalación.
$ sudo chown mosquitto: /etc/mosquitto/certs
El siguiente paso para habilitar el cifrado SSL para Mosquitto es especificar la ubicación de los certificados SSL. Abre el archivo de configuración para editarlo.
$ sudo nano /etc/mosquitto/conf.d/default.conf
Pega el siguiente código al final del archivo.
. . . listener 8883 certfile /etc/mosquitto/certs/server.pem cafile /etc/ssl/certs/ISRG_Root_X1.pem keyfile /etc/mosquitto/certs/server.key dhparamfile /etc/ssl/certs/dhparam.pem
Guarda el archivo pulsando Ctrl + X e introduciendo Y cuando se te pida. Asegúrate de dejar una nueva línea al final del archivo.
La parte listener 8883
configura la escucha encriptada. Es el puerto estándar para MQTT + SSL, denominado MQTTS. Las cuatro líneas siguientes especifican la ubicación de los archivos SSL.
Reinicia Mosquitto para actualizar la configuración.
$ sudo systemctl restart mosquitto
Tendrás que actualizar el cortafuegos para permitir las conexiones al puerto 8883.
$ sudo ufw allow 8883
A continuación, tenemos que probar la funcionalidad utilizando el comando mosquitto_pub
.
$ mosquitto_pub -h mqtt.example.com -t "home/lights/kitchen" -m "hello" -p 8883 --capath /etc/ssl/certs/ -u username -P YOUR_PASSWORD
Como puedes ver, hemos incluido algunos parámetros adicionales, como el número de puerto y la ruta a los certificados SSL. Siempre que necesites utilizar SSL, tendrás que especificar el nombre de host completo, es decir, mqtt.example.com
en lugar de localhost
; de lo contrario, daría error.
También tendrás que añadir siempre la directiva --capath
. Indica al cliente Mosquitto que busque los certificados raíz instalados por el sistema operativo.
Paso 6 – Configurar la renovación SSL
Certbot renovará automáticamente tu certificado antes de que caduque. Pero hay que decirle que copie los certificados renovados en el directorio /etc/mosquitto/certs
y que reinicie el servicio Mosquitto.
Vamos a hacerlo creando un script de shell. Crea un archivo mosquitto-copy.sh
en el directorio /etc/letsencrypt/renewal-hooks/deploy
.
$ sudo nano /etc/letsencrypt/renewal-hooks/deploy/mosquitto-copy.sh
Pega en él el siguiente código. Sustituye el valor de la variable MY_DOMAIN
por tu dominio. La variable ${RENEWED_LINEAGE}
apunta al directorio /etc/letsencrypt/live/mqtt.example.com
durante la renovación.
# Set which domain this script will be run for MY_DOMAIN=mqtt.example.com # Set the directory that the certificates will be copied to. CERTIFICATE_DIR=/etc/mosquitto/certs if [ "${RENEWED_DOMAINS}" = "${MY_DOMAIN}" ]; then # Copy new certificate to Mosquitto directory cp ${RENEWED_LINEAGE}/fullchain.pem ${CERTIFICATE_DIR}/server.pem cp ${RENEWED_LINEAGE}/privkey.pem ${CERTIFICATE_DIR}/server.key # Set ownership to Mosquitto chown mosquitto: ${CERTIFICATE_DIR}/server.pem ${CERTIFICATE_DIR}/server.key # Ensure permissions are restrictive chmod 0600 ${CERTIFICATE_DIR}/server.pem ${CERTIFICATE_DIR}/server.key # Tell Mosquitto to reload certificates and configuration pkill -HUP -x mosquitto fi
Guarda el archivo pulsando Ctrl + X e introduciendo Y cuando se te solicite.
Haz que el archivo sea ejecutable.
$ sudo chmod +x /etc/letsencrypt/renewal-hooks/deploy/mosquitto-copy.sh
Este script se ejecutará automáticamente en cada renovación correcta del certificado.
Si estás ejecutando Mosquitto y un servidor web como Nginx, tienes que indicar a Certbot que detenga el servidor antes de la renovación y lo inicie de nuevo una vez finalizada. Para ello, abre el archivo etc/letsencrypt/renewal/mqtt.example.com.conf
.
$ sudo nano /etc/letsencrypt/renewal/mqtt.example.com.conf
Añade las siguientes líneas al final del archivo. Cambia los comandos según el servidor web que estés utilizando.
pre_hook = systemctl stop nginx post_hook = systemctl start nginx
Guarda el archivo pulsando Ctrl + X e introduciendo Y cuando se te solicite.
Ejecuta un simulacro de Certbot para verificarlo.
$ sudo certbot renew --dry-run
Si no ves errores, significa que todo está configurado.
Paso 7 – Configurar Websockets
Puedes configurar Mosquitto para que utilice el protocolo MQTT desde los navegadores mediante Javascript utilizando la funcionalidad Websockets. Para activarla, abre el archivo de configuración.
$ sudo nano /etc/mosquitto/conf.d/default.conf
Pega las siguientes líneas al final del archivo.
. . . listener 8083 protocol websockets certfile /etc/mosquitto/certs/server.pem cafile /etc/ssl/certs/ISRG_Root_X1.pem keyfile /etc/mosquitto/certs/server.key dhparamfile /etc/ssl/certs/dhparam.pem
Guarda el archivo pulsando Ctrl + X e introduciendo Y cuando se te pida.
Si te fijas, es el mismo bloque que el que utilizamos para habilitar SSL, excepto por los campos de número de puerto y protocolo. 8083 es el puerto más utilizado por MQTT para hablar utilizando WebSockets.
Reinicia el servicio Mosquitto.
$ sudo systemctl restart mosquitto
Abre el puerto 8083.
$ sudo ufw allow 8083
Necesitamos utilizar un cliente MQTT basado en navegador para probar la funcionalidad de WebSockets. Hay muchos clientes disponibles, pero utilizaremos el cliente Websocket HiveMQ para nuestro propósito. Inicia el cliente en tu navegador y verás lo siguiente.
Como se muestra en la captura de pantalla anterior, rellena los campos como se indica.
- El host debe ser el dominio de tu servidor Mosquitto, mqtt.ejemplo.com.
- El puerto debe ser 8083.
- El campo ClientID puedes dejarlo como está.
- El nombre de usuario debe ser tu nombre de usuario de Mosquitto.
- La contraseña debe ser la contraseña que creaste anteriormente.
- Marca la casilla SSL.
Pulsa el botón Conectar, y el cliente HiveMQ se conectará a tu servidor Mosquitto.
Una vez conectado, introduce home/lights/kitchen
como tema, introduce cualquier mensaje y pulsa Publicar.
Aparecerá un mensaje en la ventana de tu terminal mosquitto_sub
confirmando que la conexión se ha realizado correctamente.
Esto demuestra que la implementación de Websockets se ha realizado correctamente.
Conclusión
Esto concluye nuestra configuración de un servidor MQTT seguro, protegido por contraseña y encriptado con SSL en una máquina basada en Ubuntu 20.04. Si tienes alguna pregunta, publícala en los comentarios a continuación.