Quand un client MQTT échoue avec un vague « connection failed », la cause est rarement MQTT lui-même. C'est généralement l'une des quatre couches en dessous : le DNS n'a pas résolu le nom du broker, le TCP n'a pas atteint le port, un proxy ou un pare-feu a avalé la connexion sans rien dire, ou le TLS a été intercepté et le certificat ne correspond plus. Tester ces couches dans l'ordre — DNS → TCP → TLS → MQTT — permet de trouver la couche en panne en quelques minutes.
Ce guide vous donne la commande exacte pour chaque couche, les messages d'erreur produits par chaque panne et un script Python qui exécute toute la chaîne et indique où elle casse.
Lisez d'abord le message d'erreur
Le texte de l'erreur indique déjà la couche à examiner. Voici les messages les plus recherchés :
| Erreur | Couche | Cause habituelle |
|---|---|---|
getaddrinfo ENOTFOUND broker.connectmq.com (Node.js) | DNS | Faute de frappe dans l'hôte, pas de serveur DNS, DNS split-horizon |
[Errno -2] Name or service not known (Python, Linux) | DNS | Idem |
[Errno 8] nodename nor servname provided, or not known (Python, macOS) | DNS | Idem |
getaddrinfo EAI_AGAIN | DNS | Résolveur injoignable ou en échec temporaire |
connect ETIMEDOUT / TimeoutError: timed out | TCP / pare-feu | Paquets jetés en route, mauvaise IP, port bloqué |
connect ECONNREFUSED / [Errno 111] Connection refused | TCP | Hôte joignable, rien n'écoute sur ce port |
ECONNRESET juste après la connexion | Proxy / pare-feu | Un équipement intermédiaire a coupé la connexion après l'avoir inspectée |
certificate verify failed: unable to get local issuer certificate | TLS | Bundle de CA manquant ou interception TLS |
self signed certificate in certificate chain | TLS | Proxy d'entreprise qui re-signe le trafic |
Si vous recevez déjà un CONNACK avec un reason code, le réseau fonctionne et le problème relève de l'authentification ou de la configuration — consultez la référence des reason codes.
Couche 1 : résolution DNS
Vérifiez que le nom se résout, et qu'il se résout vers les mêmes adresses partout :
dig +short broker.connectmq.com A
dig +short broker.connectmq.com AAAA
# Comparer avec un résolveur public pour repérer un split-horizon ou des enregistrements périmés
dig +short broker.connectmq.com @1.1.1.1
# Windows
nslookup broker.connectmq.comCe qu'il faut regarder :
- Aucune réponse — le nom n'existe pas dans ce résolveur. Vérifiez l'orthographe et si un VPN ou le DNS d'entreprise remplace les zones externes.
- Des réponses différentes entre votre résolveur et un résolveur public — DNS split-horizon, ancien enregistrement en cache après une migration de broker, ou filtre DNS qui renvoie l'IP d'une page de blocage.
- Un enregistrement AAAA sans route IPv6 — le client essaie d'abord IPv6 et reste bloqué jusqu'au repli. Voir problèmes IPv6 avec MQTT.
Dans un conteneur, le DNS vient du runtime de conteneurs, pas de l'hôte. Lancez le même dig dans le conteneur (docker exec -it app sh) avant de supposer que le résultat de l'hôte s'applique.
Couche 2 : joignabilité TCP et routage
La résolution fonctionne ; ouvrez maintenant une connexion TCP brute vers chaque port MQTT que vous pourriez utiliser :
nc -vz -w 5 broker.connectmq.com 1883 # MQTT sur TCP
nc -vz -w 5 broker.connectmq.com 8883 # MQTT sur TLS
nc -vz -w 5 broker.connectmq.com 8084 # MQTT sur WebSockets sécurisésTest-NetConnection broker.connectmq.com -Port 8883La différence entre un timeout et un refus est le signal le plus utile du débogage réseau :
succeeded/TcpTestSucceeded : True— le chemin est ouvert ; passez au TLS.Connection refused— vous avez atteint l'hôte, mais rien n'écoute. Mauvais port, ou broker arrêté.- Blocage puis timeout — quelque chose entre vous et le broker jette les paquets. C'est presque toujours un pare-feu.
Pour voir où les paquets s'arrêtent, tracez la route sur le vrai port, pas en ICMP (que beaucoup de réseaux traitent différemment) :
sudo traceroute -T -p 8883 broker.connectmq.com # Linux
mtr --tcp --port 8883 broker.connectmq.com # si mtr est installéSi la trace s'arrête à votre propre passerelle ou au premier saut de l'entreprise, le blocage est local. Si elle s'arrête loin, le problème est en amont ou à la bordure du broker. Un pas-à-pas complet se trouve dans tester si un port MQTT est ouvert, et les ports standards dans ports MQTT.
Couche 3 : pare-feu et proxys
Les réseaux de bureau, d'hôtel et de cloud n'autorisent souvent que le HTTP(S) sortant, via un proxy explicite. Les clients MQTT ne lisent pas HTTP_PROXY par défaut, la connexion directe finit donc simplement en timeout.
Vérifiez d'abord si un proxy est configuré :
env | grep -i _proxy
# Windows : netsh winhttp show proxyVérifiez ensuite si le proxy accepte d'ouvrir un tunnel vers le port du broker avec un CONNECT HTTP :
nc -X connect -x proxy.example.corp:3128 -vz broker.connectmq.com 8883Si le proxy refuse CONNECT vers 8883 mais autorise 443, vous avez deux options : utiliser MQTT sur WebSockets sécurisés sur un port autorisé par le proxy, ou demander à l'équipe réseau d'autoriser l'hôte du broker. Les clients dans le navigateur passent automatiquement par le proxy système, c'est pourquoi le client MQTT en ligne fonctionne souvent là où un client natif échoue. D'autres stratégies dans MQTT derrière un pare-feu d'entreprise et MQTT sur le port 443.
Couche 4 : TLS et interception
Le port TCP est ouvert, mais le TLS échoue. Regardez le certificat que le client reçoit réellement :
openssl s_client -connect broker.connectmq.com:8883 \
-servername broker.connectmq.com -showcerts </dev/null 2>/dev/null \
| openssl x509 -noout -subject -issuer -datesComparez la ligne issuer avec ce que vous obtenez depuis un partage de connexion mobile ou votre réseau domestique. Si, au bureau, l'émetteur est le nom de votre entreprise ou d'un éditeur de sécurité, un proxy à inspection TLS re-signe la connexion. Votre client MQTT la rejette avec certificate verify failed ou self signed certificate in certificate chain, ce qui est le comportement attendu.
Solutions, par ordre de préférence :
- Demandez l'exclusion de l'hôte du broker de l'inspection TLS (MQTT n'est pas du HTTP, et beaucoup de produits d'inspection le cassent de toute façon).
- Si la politique impose l'inspection, ajoutez la CA racine de l'entreprise au magasin de confiance du client — ne désactivez jamais la vérification du certificat.
- Assurez-vous que le client envoie le SNI (le
-servernameci-dessus) : sans lui, certains endpoints renvoient un autre certificat, ce qui produit des erreurs de hostname mismatch.
Si le handshake reste bloqué au lieu d'échouer, surtout via un VPN, soupçonnez un problème de MTU : les petits paquets passent, mais le gros message du certificat est jeté. Un test avec un MTU plus petit sur l'interface le confirme. Les erreurs TLS en général sont traitées dans MQTT TLS handshake failed.
Exécuter toute la chaîne avec un script
Ce script (Python 3.8+, paho-mqtt 2.x) teste chaque couche dans l'ordre, s'arrête au premier échec et affiche la durée de chaque étape :
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}")Une exécution saine affiche quatre lignes OK. Un échec indique la couche et l'exception exacte, qui correspond directement au tableau du début de cet article. Lancez-le sur la machine qui a le problème — un portable sur un autre réseau ne prouve rien sur l'appareil qui échoue.
Confirmer la correction
Après avoir modifié le DNS, les règles de pare-feu ou les paramètres de proxy, vérifiez de bout en bout plutôt que de faire confiance au changement :
- Relancez
netcheck.pysur la machine concernée et vérifiez que les quatre couches passent. - Abonnez-vous à un topic de test dans le client en ligne et publiez-y depuis l'appareil concerné.
- Laissez la connexion inactive plus longtemps que le délai supposé du pare-feu et vérifiez que les messages arrivent toujours.
Ouvrir le client en ligne pour tester la livraison
Les problèmes réseau semblent aléatoires tant qu'on ne les découpe pas en couches. Résolvez le nom, ouvrez le socket, inspectez le certificat, puis parlez MQTT : la première étape qui échoue est celle à corriger, et le message d'erreur la nomme généralement déjà.
Questions fréquentes
Pourquoi mon client MQTT fonctionne-t-il à la maison mais pas au bureau ?
Les réseaux d'entreprise bloquent souvent les ports sortants comme 1883 et 8883, imposent un proxy HTTP ou inspectent le TLS. Testez chaque couche depuis le réseau du bureau : DNS, une connexion TCP brute, l'émetteur du certificat TLS, puis MQTT. MQTT sur WebSockets via le port 443 est souvent la solution.
Comment savoir si un pare-feu bloque le trafic MQTT ?
Un pare-feu qui jette les paquets produit un timeout (ETIMEDOUT, 'timed out'), alors qu'un port fermé sur un hôte joignable répond immédiatement par 'Connection refused'. Lancez nc -vz ou Test-NetConnection sur le port et comparez avec un autre port du même hôte.
Comment détecter une interception TLS sur mon réseau ?
Lancez openssl s_client vers le broker et affichez l'émetteur du certificat. Si l'émetteur est l'autorité de votre entreprise ou d'un produit de sécurité au lieu d'une CA publique, la connexion est interceptée et votre client échouera à la vérification du certificat tant qu'il ne fait pas confiance à cette CA.

