Una captura de MQTT con Wireshark te muestra exactamente lo que tu cliente envía al broker, campo a campo. En este tutorial capturarás tu propio tráfico hacia broker.connectmq.com, el servidor MQTT público gratuito de ConnectMQ, en el puerto 1883, decodificarás paquetes CONNECT, SUBSCRIBE y PUBLISH y después repetirás la prueba en el puerto TLS 8883 para ver qué oculta el cifrado. Es la forma más rápida de depurar problemas de conexión y de comprobar por ti mismo por qué el tráfico de producción debe usar TLS.
Captura tráfico solo en redes y dispositivos que te pertenezcan o que tengas autorización para supervisar.
Qué necesitas
- Wireshark 3.x o 4.x desde el sitio oficial, con permisos de captura en tu equipo.
- Los clientes de línea de comandos de Mosquitto (
mosquitto_pubymosquitto_sub). - Opcionalmente, Python 3 con paho-mqtt 2.x para el paso de descifrado de TLS.
- Un prefijo de topic único, por ejemplo
connectmq/demo/ws-4821/.
El servidor público está abierto a todo el mundo, así que publica solo datos de prueba, nunca datos de producción; la guía enlazada arriba recoge sus límites.
Paso 1: inicia una captura con un filtro de puerto
Abre Wireshark, elige la interfaz de red que usas para acceder a internet e introduce un filtro de captura para registrar solo el tráfico MQTT:
tcp port 1883 or tcp port 8883
Inicia la captura. Wireshark reconoce MQTT en el puerto 1883 automáticamente y aplica su disector de MQTT.
Paso 2: genera algo de tráfico MQTT sin cifrar
En un terminal, suscríbete:
mosquitto_sub -h broker.connectmq.com -p 1883 -i ws-sub-4821 -V mqttv5 \
-t 'connectmq/demo/ws-4821/#' -v
En un segundo terminal, publica un mensaje normal y uno retenido:
mosquitto_pub -h broker.connectmq.com -p 1883 -i ws-pub-4821 -V mqttv5 \
-t 'connectmq/demo/ws-4821/temp' -m '{"celsius":21.7}' -q 1
mosquitto_pub -h broker.connectmq.com -p 1883 -i ws-pub-4821 -V mqttv5 \
-t 'connectmq/demo/ws-4821/status' -m 'online' -r
Detén el suscriptor con Ctrl+C y detén la captura.
Paso 3: aplica filtros de visualización de MQTT
Escribe un filtro de visualización en la barra superior. Estos son los más útiles:
| Filtro de visualización | Muestra |
|---|---|
mqtt |
Todos los paquetes MQTT decodificados |
mqtt.msgtype == 1 |
CONNECT |
mqtt.msgtype == 2 |
CONNACK |
mqtt.msgtype == 3 |
PUBLISH |
mqtt.msgtype == 8 |
SUBSCRIBE |
mqtt.msgtype == 12 or mqtt.msgtype == 13 |
PINGREQ y PINGRESP |
mqtt.msgtype == 14 |
DISCONNECT |
mqtt.topic contains "ws-4821" |
Paquetes de tu prefijo de topic |
mqtt.clientid == "ws-pub-4821" |
CONNECT de un cliente concreto |
tls |
Tráfico cifrado, normalmente en el 8883 |
Los nombres de los campos pueden variar ligeramente entre versiones de Wireshark. Si un filtro se rechaza, despliega un paquete, haz clic derecho en un campo y elige "Apply as Filter" para obtener el nombre exacto.
Paso 4: lee los paquetes decodificados
CONNECT
Selecciona un paquete CONNECT y despliega "MQ Telemetry Transport Protocol". Verás:
- Nombre y versión del protocolo (MQTT, versión 5, o 4 para 3.1.1).
- Connect flags: clean start, will flag y los flags de usuario y contraseña.
- Keep alive en segundos.
- Propiedades (MQTT 5), como el intervalo de caducidad de la sesión.
- Client ID, aquí
ws-pub-4821.
Si un cliente hubiera enviado un usuario y una contraseña por el puerto 1883, ambos serían visibles aquí en texto claro. Esa simple observación es el argumento más contundente a favor de TLS que jamás vas a necesitar.
CONNACK
El CONNACK muestra el código de motivo (0x00 significa éxito) y, en MQTT 5, propiedades del servidor como el tamaño máximo de paquete, el receive maximum, si están disponibles los mensajes retenidos y las suscripciones con comodines, y el QoS máximo. Leerlas es una forma rápida de entender los límites de un broker.
SUBSCRIBE y SUBACK
El paquete SUBSCRIBE enumera los filtros de topic con sus opciones. El SUBACK devuelve un código de motivo por filtro. Un código de 0x80 o superior significa que la suscripción fue rechazada, algo fácil de pasar por alto en los logs de la aplicación pero evidente en Wireshark.
PUBLISH
Cada PUBLISH muestra el topic, el QoS, el flag de retención, el identificador de paquete para QoS 1 y 2, las propiedades y el payload en bruto. Tu mensaje {"celsius":21.7} es legible en el panel de bytes del paquete. La publicación QoS 1 va seguida de un PUBACK del broker con el mismo identificador de paquete. Consulta los niveles de QoS de MQTT explicados para saber qué significa cada intercambio.
Paso 5: repite la prueba sobre TLS en el puerto 8883
Inicia una nueva captura con el mismo filtro y repite la publicación, esta vez usando TLS:
mosquitto_pub -h broker.connectmq.com -p 8883 --capath /etc/ssl/certs \
-i ws-pub-tls-4821 -V mqttv5 \
-t 'connectmq/demo/ws-4821/temp' -m '{"celsius":22.1}' -q 1
En Windows o macOS, apunta --cafile a un paquete de CA en lugar de usar --capath. ConnectMQ usa un certificado de Let's Encrypt, en el que confían los paquetes de CA estándar.
Aplica el filtro de visualización tls. Ahora verás:
- Un handshake TLS: ClientHello, ServerHello y, según la versión, los mensajes de certificado.
- La Server Name Indication (
broker.connectmq.com) en el ClientHello, que no está cifrada. - Registros "Application Data" sin ningún topic, client ID ni payload visible.
Un observador en la red sigue pudiendo ver que hablaste con el broker, cuándo y aproximadamente cuántos datos enviaste. No puede ver credenciales, topics ni el contenido de los mensajes. Esa es la protección que te da TLS, y la guía de configuración de TLS en MQTT explica cómo configurarlo en cada cliente.
Paso 6: descifra tu propio tráfico TLS para depurar
A veces necesitas inspeccionar el tráfico TLS de tu propio cliente durante el desarrollo. Wireshark puede descifrar TLS si el cliente escribe sus claves de sesión en un archivo de registro de claves. El módulo ssl de Python lo admite:
import ssl
import time
import paho.mqtt.client as mqtt
ctx = ssl.create_default_context()
ctx.keylog_filename = "tls-keys.log" # solo en desarrollo, nunca en producción
client = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2, client_id="ws-py-tls-4821",
protocol=mqtt.MQTTv5)
client.tls_set_context(ctx)
def on_connect(c, userdata, flags, reason_code, properties):
print("connected:", reason_code)
c.publish("connectmq/demo/ws-4821/debug", "decrypt me", qos=1)
client.on_connect = on_connect
client.connect("broker.connectmq.com", 8883, keepalive=30)
client.loop_start()
time.sleep(3)
client.loop_stop()
client.disconnect()
En Wireshark, ve a Edit > Preferences > Protocols > TLS y establece "(Pre)-Master-Secret log filename" en el archivo tls-keys.log. Como Wireshark no sabe que el puerto 8883 transporta MQTT, haz clic derecho en un paquete TLS, elige "Decode As..." y asigna el puerto 8883 a MQTT. Los paquetes descifrados mostrarán ahora los mismos campos que viste en el 1883.
Elimina después el archivo de registro de claves. Cualquiera que lo tenga puede descifrar esa captura.
Resolución de problemas con Wireshark
| Síntoma en la captura | Causa probable |
|---|---|
| SYN enviado, sin SYN-ACK | Un firewall bloquea el puerto o el nombre de host es incorrecto |
| TCP conecta, el cliente envía CONNECT y el broker cierra de inmediato | Violación del protocolo, client ID vacío o credenciales no válidas |
| CONNACK con motivo 0x86 o 0x87 | Usuario/contraseña incorrectos o no autorizado |
| CONNACK con 0x85 | Client identifier no válido |
| Alerta TLS "unknown CA" o "bad certificate" | El cliente no confía en la cadena de certificados |
| PINGREQ sin PINGRESP y después un reset | La red corta las conexiones inactivas; reduce el keep alive |
| DISCONNECT con 0x97 | Cuota superada en el broker |
| Muchos paquetes CONNECT con segundos de diferencia | Bucle de reconexión, a menudo por un client ID duplicado |
El caso del client ID duplicado es especialmente frecuente: dos dispositivos con el mismo ID se expulsan mutuamente por turnos, y Wireshark muestra el patrón al instante.
Llevarlo a producción
El servidor público es para pruebas. Para datos reales, crea un broker privado, usa el nombre de usuario, la contraseña y el client ID generados y conéctate solo sobre TLS en el 8883 o mediante WebSockets seguros en el 8084. En ConnectMQ, los brokers privados incluyen además aislamiento de tenants, cuotas, protección contra inundaciones y bloqueo de IP tras inicios de sesión fallidos repetidos. Wireshark sigue siendo útil ahí: capturar en tu lado confirma que nada sale de tu dispositivo sin cifrar. Para entender qué más puede salir mal en brokers sin protección, lee sobre los brokers MQTT expuestos.
Empieza con ConnectMQ
Prueba ahora mismo las capturas anteriores contra broker.connectmq.com y después crea un broker privado en el plan Serverless gratuito en app.connectmq.com, sin tarjeta de crédito. Tu código cliente solo necesita un nombre de host, credenciales y el puerto 8883 para pasar de las pruebas a un broker MQTT gestionado. Para consejos generales de bastionado, consulta las buenas prácticas de seguridad MQTT.
Preguntas frecuentes
¿Por qué Wireshark no muestra MQTT en el puerto 8883?
El tráfico en el 8883 está cifrado con TLS, así que Wireshark solo ve registros TLS. Puedes descifrar tus propias sesiones con un archivo de registro de claves y después usar "Decode As" para aplicar el disector de MQTT.
¿Cuál es el filtro de Wireshark para MQTT?
Usa el filtro de visualización mqtt para todos los paquetes decodificados, o mqtt.msgtype == 3 solo para los paquetes PUBLISH. Un filtro de captura tcp port 1883 limita el registro a MQTT sin cifrar.
¿Puede Wireshark ver MQTT sobre WebSockets?
Sí. En un puerto WebSocket sin cifrar, Wireshark decodifica las tramas WebSocket y puede aplicar el disector de MQTT a su payload. Los WebSockets seguros en el 8084 están cifrados igual que el puerto 8883.
¿Es legal capturar tráfico MQTT?
Capturar el tráfico de tus propios dispositivos y redes para depurar es una práctica normal. Capturar el tráfico de otras personas sin autorización no lo es, así que limita las capturas a sistemas que te pertenezcan o que tengas permiso para supervisar.



