Seguridad MQTT

Listas de control de acceso (ACL) en MQTT: conceptos y diseño

Qué son las listas de control de acceso de MQTT, cómo expresan brokers como Mosquitto las reglas de lectura y escritura por topic, cómo se comportan las operaciones denegadas y cómo diseñar espacios de nombres de topics para que la autorización siga siendo sencilla.

Diagrama de una ACL de MQTT que permite a un dispositivo escribir en su propio topic de telemetría y leer solo su topic de comandos
Pruébalo en tu propio broker MQTTConsigue un broker MQTT privado y gestionado con el plan Free y empieza con ejemplos de código listos para usar.
Pruébalo gratis Ejemplos de código Sin tarjeta

Una ACL de MQTT (lista de control de acceso) es el conjunto de reglas que usa un broker para decidir qué cliente autenticado puede publicar o suscribirse a qué topics. Este artículo explica los conceptos, muestra cómo se ven en la configuración real de un broker usando Mosquitto, describe qué ocurre cuando se deniega una operación a un cliente y ofrece patrones de diseño de topics que mantienen la autorización sencilla, tanto si usas ACL detalladas como aislamiento a nivel de tenant.

Autenticación frente a autorización

Es fácil confundirlas, y los brokers las gestionan en fases distintas:

  • La autenticación responde a "¿quién eres?". Ocurre una vez, en CONNECT, mediante usuario y contraseña, un certificado de cliente o un token. Consulta la autenticación MQTT con usuario y contraseña para más detalles.
  • La autorización responde a "¿qué puedes hacer?". Se comprueba en cada SUBSCRIBE y, según el broker, en cada PUBLISH. Las ACL son la forma más habitual de expresarla.

Un cliente autenticado sin reglas de autorización normalmente puede leer y escribir todo lo que su broker o tenant permita. Las ACL restringen eso por usuario, por client ID o por rol.

Qué contiene una regla ACL de MQTT

Sea cual sea la sintaxis del broker, cada regla combina los mismos elementos:

Elemento Ejemplos
Sujeto Un nombre de usuario, un client ID, un rol o "todos"
Acción Lectura (suscribirse y recibir), escritura (publicar) o ambas
Filtro de topic factory/line1/#, devices/+/cmd, devices/%u/#
Decisión Permitir o denegar

Las reglas se comparan con el topic de cada operación. En las suscripciones, muchos brokers comprueban el propio filtro solicitado, de modo que un cliente con permiso para leer devices/sensor-01/# no puede colar una suscripción más amplia a devices/#.

Ejemplo de ACL de MQTT en Mosquitto

Mosquitto es una referencia cómoda porque su ACL basada en archivo es breve y legible. La autenticación y el archivo ACL se activan en mosquitto.conf:

# mosquitto.conf
listener 8883
certfile /etc/mosquitto/certs/server.crt
keyfile  /etc/mosquitto/certs/server.key
allow_anonymous false
password_file /etc/mosquitto/passwd
acl_file /etc/mosquitto/acl

El archivo ACL en sí:

# /etc/mosquitto/acl

# Las reglas anteriores a cualquier línea "user" se aplican a clientes anónimos (ninguna aquí)

# Un servicio backend que lee toda la telemetría y envía comandos
user backend
topic read  factory/+/+/telemetry/#
topic write factory/+/+/cmd/#

# Un dashboard que solo puede leer
user dashboard
topic read factory/#

# Las reglas pattern se aplican a todos los usuarios.
# %u = nombre de usuario, %c = client ID
pattern write factory/+/%c/telemetry/#
pattern read  factory/+/%c/cmd/#
pattern write factory/+/%c/status

Con estas reglas, un dispositivo que se conecta con el client ID cnc-07 puede publicar en factory/line2/cnc-07/telemetry/spindle y recibir factory/line2/cnc-07/cmd/stop, pero no puede leer los comandos de otra máquina ni publicar como otra máquina. Las reglas pattern escalan a miles de dispositivos sin una entrada por dispositivo, que es el principal motivo para incluir el client ID en la ruta del topic. Mosquitto también admite líneas topic deny y un plugin de seguridad dinámica con roles y grupos; la documentación de Mosquitto cubre ambos.

Recarga el broker después de editar el archivo y luego prueba:

# Permitido: cnc-07 publica su propia telemetría
mosquitto_pub -h localhost -p 8883 --cafile ca.crt -V mqttv5 \
  -i cnc-07 -u cnc-07 -P "$PW" -t 'factory/line2/cnc-07/telemetry/spindle' -m 1200 -q 1

# Denegado: cnc-07 publica como cnc-08
mosquitto_pub -h localhost -p 8883 --cafile ca.crt -V mqttv5 \
  -i cnc-07 -u cnc-07 -P "$PW" -t 'factory/line2/cnc-08/telemetry/spindle' -m 1200 -q 1

Qué ocurre cuando se deniega una operación

Las operaciones denegadas no siempre producen un error evidente, y por eso los problemas de ACL son famosos por lo difíciles que resultan de depurar.

Operación MQTT 3.1.1 MQTT 5.0
SUBSCRIBE denegado Código de retorno de SUBACK 0x80 (fallo) Código de motivo de SUBACK 0x87 Not authorized
PUBLISH QoS 0 denegado Se descarta en silencio Se descarta en silencio
PUBLISH QoS 1/2 denegado Normalmente se confirma y se descarta PUBACK/PUBREC puede llevar 0x87, según el broker

Consejos prácticos de depuración:

  1. Revisa siempre los códigos de SUBACK. Muchas bibliotecas los exponen en un callback; regístralos en el arranque.
  2. Usa MQTT 5 y QoS 1 al hacer pruebas. Los códigos de motivo en las confirmaciones hacen visibles las denegaciones.
  3. Prueba con la identidad del dispositivo. Probar con una cuenta de administrador no demuestra nada sobre las reglas del dispositivo.
  4. Consulta el log del broker. La mayoría de los brokers registran las publicaciones y suscripciones denegadas en nivel de depuración.

Diseñar espacios de nombres de topics para una autorización sencilla

Las buenas ACL empiezan con buenos topics. Si la identidad y la dirección son visibles en la ruta del topic, las reglas se reducen a unos pocos patrones. Si no lo son, acabas con una larga lista de casos especiales.

Incluye la identidad en la ruta

Incluye el client ID o el ID del dispositivo en un nivel fijo: factory/<line>/<deviceId>/.... Las reglas pattern como %c solo funcionan cuando la identidad ocupa un nivel completo del topic.

Separa las direcciones

Usa ramas distintas para los datos que suben y los comandos que bajan: .../telemetry, .../status, .../cmd. Los dispositivos tienen permiso de escritura en las dos primeras y de lectura en la tercera.

Separa tenants o clientes en el nivel superior

Si un broker da servicio a varios clientes, haz que el cliente sea el primer nivel: <tenant>/.... Así, las credenciales de cada tenant quedan limitadas a un subárbol.

Mantén los datos compartidos en una rama con un nombre claro

La configuración que se difunde a todos los dispositivos va en broadcast/... o config/..., con acceso de solo lectura para los dispositivos.

El artículo de ejemplos de jerarquías de topics MQTT muestra árboles completos construidos sobre estos principios.

Lista de comprobación para el diseño de ACL

  1. Deniega por defecto; permite solo lo que necesita cada rol.
  2. Da a los dispositivos escritura en su propia telemetría y estado, lectura en sus propios comandos y nada más.
  3. Da a los dashboards acceso de solo lectura.
  4. Da a los servicios backend escritura en las ramas de comandos y audita quién tiene esas credenciales.
  5. Nunca concedas # a una credencial de dispositivo.
  6. Mantén el archivo de reglas o las definiciones de roles en control de versiones y revisa los cambios.
  7. Prueba cada rol con sus credenciales reales después de cada cambio.

Autorización en ConnectMQ

ConnectMQ no ofrece ACL por topic. El aislamiento en ConnectMQ funciona a nivel de tenant: el tráfico del broker de cada cliente está aislado del de todos los demás tenants, las credenciales se generan por broker y los client IDs están vinculados al usuario y la contraseña emitidos, por lo que un cliente no puede reclamar la identidad de otro. Las cuotas por plan, la protección contra inundaciones y el bloqueo de IP tras inicios de sesión fallidos repetidos limitan lo que puede hacer un cliente con mal comportamiento.

Lo que esto implica para el diseño:

  • Usa brokers separados como frontera de seguridad. Si dos grupos de clientes nunca deben ver los datos del otro, ponlos en brokers diferentes en lugar de confiar en reglas de topics. Un plan Dedicated te da un clúster aislado cuando esa frontera también debe ser física.
  • Mantén a los clientes no confiables fuera del broker. Los usuarios de navegador y los terceros deben hablar con tu backend, que guarda las credenciales del broker y decide qué publicar en su nombre.
  • Diseña los topics como si las ACL pudieran llegar más adelante. Incluir la identidad en la ruta y separar las ramas de comandos no cuesta nada ahora y te deja opciones abiertas si trasladas parte del sistema a un broker con reglas de topics.
  • Valida los comandos en el dispositivo. Un dispositivo debe comprobar que un comando está bien formado y es esperado antes de actuar, independientemente de cómo lo autorice el broker.

Esta combinación de aislamiento de tenants y disciplina en los topics cubre bien muchas flotas. Si tu proyecto necesita restricciones de topics por dispositivo dentro de un espacio de nombres compartido, planifica un broker con ACL a nivel de topic para esa parte del sistema. Para tener una visión global, consulta las buenas prácticas de seguridad MQTT y ¿es seguro MQTT?.

Empieza con ConnectMQ

Ejecuta tus dispositivos en un broker MQTT gestionado con aislamiento de tenants, TLS, credenciales generadas vinculadas a client IDs y bloqueo de IP ante inicios de sesión fallidos. Crea un broker Serverless gratuito en app.connectmq.com, sin tarjeta de crédito, y prueba primero tus diseños de topics en el servidor MQTT público gratuito de broker.connectmq.com, pensado para pruebas y prototipos, no para datos de producción.

Preguntas frecuentes

¿Qué es una ACL de MQTT?

Es una lista de reglas que indica a un broker qué usuarios o clientes pueden publicar o suscribirse a qué filtros de topic. Se comprueba después de que el cliente se haya autenticado.

¿ConnectMQ admite ACL por topic?

No. ConnectMQ aísla a los tenants entre sí y vincula los client IDs a las credenciales de usuario y contraseña emitidas, pero no aplica reglas de lectura y escritura por topic dentro de un broker.

¿Por qué mi publicación denegada no devuelve ningún error?

En MQTT 3.1.1 el broker no tiene forma de informar de una publicación denegada, así que la descarta en silencio. Los brokers MQTT 5 pueden devolver el código de motivo 0x87 en las confirmaciones de QoS 1 y 2.

¿Las reglas ACL deben usar el nombre de usuario o el client ID?

Usa el identificador que sea único por dispositivo y que el cliente no pueda elegir libremente. Si el broker vincula los client IDs a las credenciales, cualquiera de los dos sirve; si no, es preferible el nombre de usuario.

Artículos relacionados

Cómo rotar credenciales MQTT sin tiempo de inactividad

Una estrategia de doble credencial paso a paso para rotar usuarios y contraseñas MQTT en toda una flota: prepara la nueva credencial, cambia con respaldo, verifica y solo entonces revoca la antigua.

8 min de lectura

Todos los artículos →

Tu broker MQTT privado, a unos pocos clics

Crea una cuenta, obtén las credenciales de tu broker y conecta tu primer dispositivo, sin servidores que instalar, parchear ni escalar.