Cuando un cliente MQTT falla con un vago "connection failed", la causa casi nunca es MQTT. Suele ser una de las cuatro capas que hay debajo: DNS no pudo resolver el nombre del broker, TCP no pudo alcanzar el puerto, un proxy o firewall se tragó la conexión en silencio, o el TLS fue interceptado y el certificado ya no coincide. Probar esas capas en orden — DNS → TCP → TLS → MQTT — encuentra la que falla en pocos minutos.
Esta guía te da el comando exacto para cada capa, los mensajes de error que produce cada fallo y un script en Python que ejecuta toda la cadena y te dice dónde se rompe.
Lee primero el mensaje de error
El texto del error ya te indica qué capa mirar. Estos son los mensajes que más se buscan:
| Error | Capa | Causa habitual |
|---|---|---|
getaddrinfo ENOTFOUND broker.connectmq.com (Node.js) | DNS | Host mal escrito, sin servidor DNS, DNS split-horizon |
[Errno -2] Name or service not known (Python, Linux) | DNS | Igual que arriba |
[Errno 8] nodename nor servname provided, or not known (Python, macOS) | DNS | Igual que arriba |
getaddrinfo EAI_AGAIN | DNS | Resolver inalcanzable o con fallos temporales |
connect ETIMEDOUT / TimeoutError: timed out | TCP / firewall | Paquetes descartados en el camino, IP errónea, puerto bloqueado |
connect ECONNREFUSED / [Errno 111] Connection refused | TCP | Host alcanzable, nada escuchando en ese puerto |
ECONNRESET justo después de conectar | Proxy / firewall | Un equipo intermedio cortó la conexión tras inspeccionarla |
certificate verify failed: unable to get local issuer certificate | TLS | Falta el bundle de CAs o hay intercepción TLS |
self signed certificate in certificate chain | TLS | Proxy corporativo que vuelve a firmar el tráfico |
Si ya recibes un CONNACK con un reason code, la red está bien y el problema es de autenticación o configuración: búscalo en la referencia de reason codes.
Capa 1: resolución DNS
Comprueba que el nombre se resuelve, y que se resuelve a las mismas direcciones en todas partes:
dig +short broker.connectmq.com A
dig +short broker.connectmq.com AAAA
# Compara con un resolver público para detectar split-horizon o registros obsoletos
dig +short broker.connectmq.com @1.1.1.1
# Windows
nslookup broker.connectmq.comQué buscar:
- Sin respuesta: el nombre no existe en este resolver. Revisa la ortografía y si una VPN o el DNS corporativo sobrescriben zonas externas.
- Respuestas distintas entre tu resolver y uno público: DNS split-horizon, un registro antiguo en caché tras una migración del broker o un filtro DNS que devuelve la IP de una página de bloqueo.
- Un registro AAAA pero sin ruta IPv6: el cliente prueba IPv6 primero y se queda colgado hasta que hace fallback. Consulta problemas de IPv6 en MQTT.
Dentro de contenedores, el DNS lo proporciona el runtime, no el host. Ejecuta el mismo dig dentro del contenedor (docker exec -it app sh) antes de suponer que el resultado del host aplica.
Capa 2: alcance TCP y enrutamiento
La resolución funciona; ahora abre una conexión TCP directa a cada puerto MQTT que puedas usar:
nc -vz -w 5 broker.connectmq.com 1883 # MQTT sobre TCP
nc -vz -w 5 broker.connectmq.com 8883 # MQTT sobre TLS
nc -vz -w 5 broker.connectmq.com 8084 # MQTT sobre WebSockets segurosTest-NetConnection broker.connectmq.com -Port 8883La diferencia entre un timeout y un rechazo es la señal más útil en la depuración de red:
succeeded/TcpTestSucceeded : True: el camino está abierto; pasa a TLS.Connection refused: llegaste al host, pero nada escucha ahí. Puerto equivocado o broker caído.- Se queda colgado y luego da timeout: algo entre tú y el broker descarta los paquetes. Casi siempre es un firewall.
Para ver dónde se detienen los paquetes, traza la ruta en el puerto real, no con ICMP (que muchas redes tratan de otra manera):
sudo traceroute -T -p 8883 broker.connectmq.com # Linux
mtr --tcp --port 8883 broker.connectmq.com # si tienes mtr instaladoSi la traza muere en tu propio gateway o en el primer salto corporativo, el bloqueo es local. Si muere lejos, el problema está aguas arriba o en el borde del broker. Tienes un recorrido completo en comprobar si un puerto MQTT está abierto, y los números de puerto estándar en puertos MQTT.
Capa 3: firewalls y proxies
Las redes de oficinas, hoteles y nubes a menudo solo permiten salir HTTP(S) a través de un proxy explícito. Los clientes MQTT no leen HTTP_PROXY por defecto, así que la conexión directa simplemente da timeout.
Primero, averigua si hay un proxy configurado:
env | grep -i _proxy
# Windows: netsh winhttp show proxyDespués comprueba si el proxy hará un túnel hasta el puerto del broker con un CONNECT HTTP:
nc -X connect -x proxy.example.corp:3128 -vz broker.connectmq.com 8883Si el proxy rechaza CONNECT al 8883 pero permite el 443, tienes dos opciones: usar MQTT sobre WebSockets seguros en un puerto que el proxy permita, o pedir al equipo de red que autorice el host del broker. Los clientes basados en navegador pasan automáticamente por el proxy del sistema, por eso el cliente MQTT online suele funcionar en redes donde un cliente nativo falla. Tienes más estrategias en MQTT detrás de un firewall corporativo y MQTT por el puerto 443.
Capa 4: TLS e intercepción
El puerto TCP está abierto, pero el TLS falla. Mira el certificado que el cliente recibe realmente:
openssl s_client -connect broker.connectmq.com:8883 \
-servername broker.connectmq.com -showcerts </dev/null 2>/dev/null \
| openssl x509 -noout -subject -issuer -datesCompara la línea issuer con lo que obtienes desde el hotspot del móvil o la red de casa. Si en la oficina aparece como emisor el nombre de tu empresa o de un proveedor de seguridad, un proxy con inspección TLS está volviendo a firmar la conexión. Tu cliente MQTT la rechaza con certificate verify failed o self signed certificate in certificate chain, y es el comportamiento correcto.
Soluciones, por orden de preferencia:
- Pide que el host del broker se excluya de la inspección TLS (MQTT no es HTTP, y muchos productos de inspección lo rompen de todos modos).
- Si la política exige inspección, añade la CA raíz corporativa al almacén de confianza del cliente; nunca desactives la verificación del certificado.
- Asegúrate de que el cliente envía SNI (el
-servernamede arriba): sin él, algunos endpoints devuelven otro certificado, lo que produce errores de hostname mismatch.
Si el handshake se queda colgado en lugar de fallar, sobre todo en una VPN, sospecha de un problema de MTU: los paquetes pequeños pasan, pero el mensaje grande del certificado se descarta. Probar con un MTU menor en la interfaz lo confirma. Los errores de TLS en general se tratan en MQTT TLS handshake failed.
Ejecuta toda la cadena con un script
Este script (Python 3.8+, paho-mqtt 2.x) prueba cada capa en orden, se detiene en el primer fallo e imprime el tiempo de cada paso:
import os, socket, ssl, sys, time
import paho.mqtt.client as mqtt
HOST, PORT = "broker.connectmq.com", 8883
def dns():
infos = socket.getaddrinfo(HOST, PORT, proto=socket.IPPROTO_TCP)
return ", ".join(sorted({i[4][0] for i in infos}))
def tcp():
with socket.create_connection((HOST, PORT), timeout=5) as s:
return f"connected to {s.getpeername()[0]}"
def tls():
ctx = ssl.create_default_context()
with socket.create_connection((HOST, PORT), timeout=5) as raw:
with ctx.wrap_socket(raw, server_hostname=HOST) as s:
issuer = dict(x[0] for x in s.getpeercert()["issuer"])
return f"{s.version()}, issuer: {issuer.get('organizationName')}"
def mqtt_connect():
result = {}
c = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2, protocol=mqtt.MQTTv5)
c.on_connect = lambda cl, ud, flags, reason, props: result.setdefault("rc", reason)
if os.getenv("MQTT_USER"):
c.username_pw_set(os.getenv("MQTT_USER"), os.getenv("MQTT_PASS"))
c.tls_set()
c.connect(HOST, PORT, keepalive=30)
c.loop_start()
for _ in range(50):
if "rc" in result:
break
time.sleep(0.1)
c.disconnect()
c.loop_stop()
if "rc" not in result:
raise TimeoutError("no CONNACK within 5 s")
if result["rc"].is_failure:
raise RuntimeError(f"CONNACK: {result['rc']}")
return f"CONNACK: {result['rc']}"
for name, step in [("DNS", dns), ("TCP", tcp), ("TLS", tls), ("MQTT", mqtt_connect)]:
start = time.perf_counter()
try:
info = step()
except Exception as e:
print(f"FAIL {name:<5} {type(e).__name__}: {e}")
sys.exit(1)
print(f"OK {name:<5} {(time.perf_counter() - start) * 1000:6.0f} ms {info}")Una ejecución sana imprime cuatro líneas OK. Un fallo te indica la capa y la excepción exacta, que corresponde directamente a la tabla del inicio de este artículo. Ejecútalo en la máquina que tiene el problema: un portátil en otra red no demuestra nada sobre el dispositivo que falla.
Confirma la solución
Después de cambiar el DNS, las reglas del firewall o la configuración del proxy, verifica de extremo a extremo en lugar de fiarte del cambio:
- Vuelve a ejecutar
netcheck.pyen la máquina afectada y confirma que las cuatro capas pasan. - Suscríbete a un topic de prueba en el cliente online y publica en él desde el dispositivo afectado.
- Deja la conexión inactiva más tiempo que el timeout sospechado del firewall y comprueba que los mensajes siguen llegando.
Abre el cliente online para probar la entrega
Los problemas de red parecen aleatorios hasta que los separas en capas. Resuelve el nombre, abre el socket, inspecciona el certificado y después habla MQTT: el primer paso que falle es el que hay que arreglar, y el mensaje de error normalmente ya lo nombra.
Preguntas frecuentes
¿Por qué mi cliente MQTT funciona en casa pero no en la oficina?
Las redes corporativas suelen bloquear puertos salientes como 1883 y 8883, obligan a pasar por un proxy HTTP o inspeccionan el TLS. Prueba cada capa desde la red de la oficina: DNS, una conexión TCP directa, el emisor del certificado TLS y luego MQTT. MQTT sobre WebSockets en el puerto 443 suele ser la salida.
¿Cómo sé si un firewall está descartando el tráfico MQTT?
Un firewall que descarta paquetes produce un timeout (ETIMEDOUT, 'timed out'), mientras que un puerto cerrado en un host alcanzable responde al instante con 'Connection refused'. Ejecuta nc -vz o Test-NetConnection contra el puerto y compáralo con otro puerto del mismo host.
¿Cómo detecto la intercepción TLS en mi red?
Ejecuta openssl s_client contra el broker e imprime el emisor del certificado. Si el emisor es la CA de tu empresa o de un producto de seguridad en lugar de una CA pública, la conexión está siendo interceptada y tu cliente fallará la verificación del certificado salvo que confíe en esa CA.

