Guías

Proteger Mosquitto: contraseñas, ACL y TLS

Protege un broker Mosquitto paso a paso: crea un archivo de contraseñas con mosquitto_passwd, limita topics con un ACL usando %u y %c y activa TLS en el 8883.

Actualizado · 8 min de lectura

Una instalación nueva de Mosquitto 2.x rechaza a los clientes remotos anónimos, lo cual es un buen comienzo — pero para usarlo de verdad necesitas tres capas: autenticación (¿quién eres?), autorización (¿qué topics puedes tocar?) y cifrado (¿puede alguien en la red leer esto?). En Mosquitto, son el archivo de contraseñas, el archivo ACL y un listener TLS. Esta guía configura las tres.

Si todavía no tienes el broker instalado, empieza por instalar Mosquitto o por ejecutarlo en Docker. Las rutas siguientes suponen una instalación por paquete en Linux; en Docker, usa /mosquitto/config/ en lugar de /etc/mosquitto/.

1. Crea un archivo de contraseñas con mosquitto_passwd

mosquitto_passwd guarda los nombres de usuario con hashes de contraseña con sal (nunca en texto plano). Crea el archivo con el primer usuario y luego añade más:

Crear usuarios
# -c creates a NEW file and overwrites any existing one — first user only
sudo mosquitto_passwd -c /etc/mosquitto/passwd alice

# add or update users (prompts for the password)
sudo mosquitto_passwd /etc/mosquitto/passwd sensor-01

# non-interactive, e.g. in provisioning scripts
sudo mosquitto_passwd -b /etc/mosquitto/passwd bob 'S3cure-pass'

# delete a user
sudo mosquitto_passwd -D /etc/mosquitto/passwd bob

Evita -b en máquinas compartidas: la contraseña acaba en el historial de tu shell y en la lista de procesos. Protege el archivo para que solo el broker pueda leerlo:

bash
sudo chown mosquitto:mosquitto /etc/mosquitto/passwd
sudo chmod 0700 /etc/mosquitto/passwd

Ahora indica al broker que lo use:

/etc/mosquitto/conf.d/secure.conf
listener 1883
allow_anonymous false
password_file /etc/mosquitto/passwd
Pruébalo
sudo systemctl restart mosquitto

# should fail with "not authorised"
mosquitto_pub -h localhost -t test -m hi

# should succeed
mosquitto_pub -h localhost -u alice -P 'your-password' -t test -m hi

2. Restringe los topics con un archivo ACL

Un archivo de contraseñas por sí solo permite a cualquier usuario autenticado leer y escribir en todos los topics. Un archivo ACL lo limita. En cuanto se define acl_file, todo lo que no esté permitido explícitamente queda denegado.

/etc/mosquitto/acl
# --- pattern rules apply to every authenticated client ---
# each device may read and write only below its own username
pattern readwrite devices/%u/#
# each client may read its own command topic, keyed by client ID
pattern read commands/%c

# --- user-specific rules ---
user alice
topic readwrite #

user dashboard
topic read devices/#
topic write commands/+

user sensor-01
topic write telemetry/sensor-01/#
DirectivaSignificado
user <name>Las líneas topic siguientes se aplican a este nombre de usuario
topic [read|write|readwrite|deny] <filter>Concede (o, con deny, bloquea) el acceso; se permiten los comodines + y #. Omitir el tipo de acceso equivale a readwrite
pattern [access] <filter>Se aplica a todos los clientes; %u se sustituye por el nombre de usuario y %c por el client ID

Actívalo junto al archivo de contraseñas:

/etc/mosquitto/conf.d/secure.conf
listener 1883
allow_anonymous false
password_file /etc/mosquitto/passwd
acl_file /etc/mosquitto/acl

Hay dos comportamientos que pillan a la gente. Primero, una publicación en un topic prohibido se descarta en silencio en MQTT 3.1.1 — el cliente no ve ningún error (los clientes MQTT 5 reciben un código de motivo en el PUBACK de QoS 1/2). Segundo, una suscripción prohibida se rechaza en el SUBACK, algo que muchas librerías cliente no muestran. Cuando “los mensajes simplemente no llegan”, revisa primero la ACL y ejecuta el broker con log_type all mientras depuras. Usa el probador de topics para comprobar qué topics cubre realmente un filtro como devices/+/#.

3. Cifra el tráfico con TLS

Sin TLS, los nombres de usuario, las contraseñas y los payloads cruzan la red en texto plano. La convención es MQTT sobre TLS en el puerto 8883 (consulta los puertos MQTT). Necesitas un certificado, su clave privada y — en configuraciones autofirmadas — el certificado de la CA.

/etc/mosquitto/conf.d/tls.conf
# MQTT over TLS
listener 8883
certfile /etc/mosquitto/certs/server.crt
keyfile  /etc/mosquitto/certs/server.key
# cafile is only needed for self-signed / private CA chains or client certificates
# cafile /etc/mosquitto/certs/ca.crt

# Secure WebSockets for browser clients
listener 8884
protocol websockets
certfile /etc/mosquitto/certs/server.crt
keyfile  /etc/mosquitto/certs/server.key

Cuando TLS funcione, elimina o bloquea con el firewall el listener 1883 sin cifrar (o lígalo a localhost con listener 1883 127.0.0.1) para que las credenciales no puedan filtrarse por él. Para exigir certificados de cliente (TLS mutuo), añade cafile y require_certificate true al listener; si añades use_identity_as_username true, el CN del certificado pasa a ser el nombre de usuario a efectos de ACL.

Pruébalo desde un cliente:

bash
# public CA (e.g. Let's Encrypt): use the system trust store
mosquitto_sub -h mqtt.example.com -p 8883 --capath /etc/ssl/certs \
  -u alice -P 'your-password' -t 'devices/#' -v

# self-signed / private CA
mosquitto_sub -h mqtt.example.com -p 8883 --cafile ca.crt \
  -u alice -P 'your-password' -t 'devices/#' -v

El nombre de host de -h debe coincidir con el CN/SAN del certificado; si no, la verificación falla. Tienes más opciones de CLI en la chuleta de mosquitto_pub/sub.

Usar un certificado de Let's Encrypt

Un certificado de confianza pública significa que los clientes no necesitan un archivo de CA personalizado. Consigue uno con certbot para el nombre de host de tu broker (el puerto 80 debe ser accesible para el desafío HTTP) y apunta Mosquitto a los archivos de live:

ini
listener 8883
certfile /etc/letsencrypt/live/mqtt.example.com/fullchain.pem
keyfile  /etc/letsencrypt/live/mqtt.example.com/privkey.pem
  • Usa fullchain.pem, no cert.pem — los clientes necesitan el certificado intermedio.
  • El usuario mosquitto debe poder leer la clave; por defecto /etc/letsencrypt solo es accesible para root. Muchas instalaciones copian los archivos a /etc/mosquitto/certs/ con un deploy hook de certbot y ajustan allí el propietario.
  • Los certificados se renuevan cada pocos meses. Añade systemctl reload mosquitto al deploy hook para que el broker cargue el nuevo certificado.

Todo junto

/etc/mosquitto/conf.d/secure.conf
listener 1883 127.0.0.1

listener 8883
certfile /etc/mosquitto/certs/fullchain.pem
keyfile  /etc/mosquitto/certs/privkey.pem

listener 8884
protocol websockets
certfile /etc/mosquitto/certs/fullchain.pem
keyfile  /etc/mosquitto/certs/privkey.pem

allow_anonymous false
password_file /etc/mosquitto/passwd
acl_file /etc/mosquitto/acl

En lugar de editarlo a mano, puedes generarlo con el generador de mosquitto.conf. Para una visión más amplia — políticas de client ID, límites de tasa, monitorización — lee las buenas prácticas de seguridad MQTT, y si los clientes empiezan a fallar con “not authorised”, la guía de errores de conexión explica cada código.

Preguntas frecuentes

¿Cómo recargo el archivo de contraseñas de Mosquitto sin reiniciar?

Envía al broker un SIGHUP, por ejemplo con sudo systemctl reload mosquitto o con kill -HUP y el PID del broker. Mosquitto vuelve a leer el archivo de contraseñas y el archivo ACL al recibir SIGHUP, así que los clientes existentes siguen conectados.

¿Qué significa %u en un archivo ACL de Mosquitto?

En una línea pattern, %u se sustituye por el nombre de usuario del cliente que se conecta y %c por su client ID. pattern readwrite devices/%u/# permite que cada usuario acceda solo a los topics que cuelgan de su propio nombre.

¿Puede Mosquitto usar un certificado de Let’s Encrypt?

Sí. Apunta certfile a fullchain.pem y keyfile a privkey.pem, asegúrate de que el usuario mosquitto pueda leerlos y recarga el broker tras cada renovación. Los clientes verifican entonces el servidor con el almacén de CA del sistema.