Broker-Tests

MQTT-Netzwerkprobleme diagnostizieren: DNS, Firewalls und Proxys

Finde heraus, warum dein MQTT-Client den Broker nicht erreicht: DNS, TCP-Routing, Firewalls, Firmen-Proxys und TLS-Interception Schicht für Schicht testen.

Aktualisiert · 9 Min. Lesezeit

MQTT-Netzwerkprobleme diagnostizieren: DNS, Firewalls und Proxys

Wenn ein MQTT-Client mit einem vagen „connection failed" scheitert, liegt es selten an MQTT selbst. Meist ist eine der vier Schichten darunter schuld: DNS konnte den Broker-Namen nicht auflösen, TCP erreichte den Port nicht, ein Proxy oder eine Firewall hat die Verbindung stillschweigend geschluckt, oder TLS wurde abgefangen und das Zertifikat passt nicht mehr. Wenn du diese Schichten der Reihe nach testest — DNS → TCP → TLS → MQTT —, findest du die kaputte in wenigen Minuten.

Diese Anleitung liefert dir den genauen Befehl für jede Schicht, die Fehlermeldungen, die jeder Fehler erzeugt, und ein Python-Skript, das die ganze Kette durchläuft und dir sagt, wo sie bricht.

Zuerst die Fehlermeldung lesen

Der Fehlertext verrät bereits, welche Schicht du dir ansehen musst. Das sind die am häufigsten gesuchten Meldungen:

FehlerSchichtTypische Ursache
getaddrinfo ENOTFOUND broker.connectmq.com (Node.js)DNSTippfehler im Host, kein DNS-Server, Split-Horizon-DNS
[Errno -2] Name or service not known (Python, Linux)DNSWie oben
[Errno 8] nodename nor servname provided, or not known (Python, macOS)DNSWie oben
getaddrinfo EAI_AGAINDNSResolver nicht erreichbar oder vorübergehend gestört
connect ETIMEDOUT / TimeoutError: timed outTCP / FirewallPakete unterwegs verworfen, falsche IP, blockierter Port
connect ECONNREFUSED / [Errno 111] Connection refusedTCPHost erreichbar, aber nichts lauscht auf dem Port
ECONNRESET direkt nach dem VerbindenProxy / FirewallEine Middlebox hat die Verbindung nach der Inspektion getrennt
certificate verify failed: unable to get local issuer certificateTLSFehlendes CA-Bundle oder TLS-Interception
self signed certificate in certificate chainTLSFirmen-Proxy signiert den Traffic neu

Bekommst du bereits ein CONNACK mit Reason Code, ist das Netzwerk in Ordnung und das Problem liegt bei Authentifizierung oder Konfiguration — schlag ihn in der Reason-Code-Referenz nach.

Schicht 1: DNS-Auflösung

Prüfe, ob der Name aufgelöst wird — und zwar überall auf dieselben Adressen:

Broker-Namen auflösen
dig +short broker.connectmq.com A
dig +short broker.connectmq.com AAAA

# Mit einem öffentlichen Resolver vergleichen, um Split-Horizon oder veraltete Einträge zu finden
dig +short broker.connectmq.com @1.1.1.1

# Windows
nslookup broker.connectmq.com

Worauf du achten solltest:

  • Keine Antwort — der Name existiert in diesem Resolver nicht. Prüfe die Schreibweise und ob ein VPN oder das Firmen-DNS externe Zonen überschreibt.
  • Unterschiedliche Antworten von deinem und einem öffentlichen Resolver — Split-Horizon-DNS, ein alter gecachter Eintrag nach einer Broker-Migration oder ein DNS-Filter, der die IP einer Sperrseite liefert.
  • Ein AAAA-Eintrag, aber keine IPv6-Route — der Client versucht zuerst IPv6 und hängt, bis er zurückfällt. Siehe MQTT-IPv6-Probleme.

In Containern kommt DNS von der Container-Runtime, nicht vom Host. Führe dasselbe dig im Container aus (docker exec -it app sh), bevor du annimmst, dass das Host-Ergebnis gilt.

Schicht 2: TCP-Erreichbarkeit und Routing

Die Auflösung klappt; öffne jetzt eine rohe TCP-Verbindung zu jedem MQTT-Port, den du nutzen könntest:

MQTT-Ports testen
nc -vz -w 5 broker.connectmq.com 1883   # MQTT über TCP
nc -vz -w 5 broker.connectmq.com 8883   # MQTT über TLS
nc -vz -w 5 broker.connectmq.com 8084   # MQTT über sichere WebSockets
Windows PowerShell
Test-NetConnection broker.connectmq.com -Port 8883

Der Unterschied zwischen einem Timeout und einer Ablehnung ist das nützlichste Signal beim Netzwerk-Debugging:

  • succeeded / TcpTestSucceeded : True — der Weg ist frei; weiter zu TLS.
  • Connection refused — du hast den Host erreicht, aber dort lauscht nichts. Falscher Port oder Broker down.
  • Hängt und läuft dann in einen Timeout — irgendetwas zwischen dir und dem Broker verwirft die Pakete. Fast immer eine Firewall.

Um zu sehen, wo die Pakete stehen bleiben, verfolge die Route auf dem echten Port, nicht per ICMP (das viele Netze anders behandeln):

TCP-Pfad verfolgen
sudo traceroute -T -p 8883 broker.connectmq.com   # Linux
mtr --tcp --port 8883 broker.connectmq.com        # falls mtr installiert ist

Endet der Trace an deinem eigenen Gateway oder am ersten Firmen-Hop, ist die Sperre lokal. Endet er weit entfernt, liegt das Problem weiter vorne oder am Rand des Brokers. Eine vollständige Anleitung für Port-Checks findest du unter testen, ob ein MQTT-Port offen ist, die Standard-Ports unter MQTT-Ports.

Schicht 3: Firewalls und Proxys

Büro-, Hotel- und Cloud-Netze erlauben ausgehend oft nur HTTP(S) über einen expliziten Proxy. MQTT-Clients lesen HTTP_PROXY standardmäßig nicht, also läuft die direkte Verbindung einfach in einen Timeout.

Finde zuerst heraus, ob ein Proxy konfiguriert ist:

Proxy-Einstellungen suchen
env | grep -i _proxy
# Windows: netsh winhttp show proxy

Prüfe dann, ob der Proxy per HTTP-CONNECT einen Tunnel zum Broker-Port aufbaut:

Tunnel durch einen HTTP-Proxy
nc -X connect -x proxy.example.corp:3128 -vz broker.connectmq.com 8883

Lehnt der Proxy CONNECT auf 8883 ab, erlaubt aber 443, hast du zwei Optionen: MQTT über sichere WebSockets auf einem Port, den der Proxy zulässt, oder das Netzwerkteam bitten, den Broker-Host freizugeben. Browserbasierte Clients gehen automatisch über den System-Proxy — deshalb funktioniert der Online-MQTT-Client oft in Netzen, in denen ein nativer Client scheitert. Weitere Strategien findest du unter MQTT hinter einer Firmen-Firewall und MQTT über Port 443.

Schicht 4: TLS und Interception

Der TCP-Port ist offen, aber TLS schlägt fehl. Sieh dir das Zertifikat an, das der Client tatsächlich erhält:

Zertifikatskette untersuchen
openssl s_client -connect broker.connectmq.com:8883 \
  -servername broker.connectmq.com -showcerts </dev/null 2>/dev/null \
  | openssl x509 -noout -subject -issuer -dates

Vergleiche die Zeile issuer mit dem Ergebnis über einen Handy-Hotspot oder dein Heimnetz. Zeigt das Büro als Aussteller deinen Firmennamen oder einen Security-Anbieter, signiert ein TLS-inspizierender Proxy die Verbindung neu. Dein MQTT-Client lehnt sie mit certificate verify failed oder self signed certificate in certificate chain ab — und das ist korrektes Verhalten.

Lösungen, nach Präferenz geordnet:

  1. Bitte darum, den Broker-Host von der TLS-Inspektion auszunehmen (MQTT ist kein HTTP, und viele Inspektionsprodukte machen es ohnehin kaputt).
  2. Verlangt die Richtlinie Inspektion, füge die Root-CA der Firma zum Trust Store des Clients hinzu — deaktiviere niemals die Zertifikatsprüfung.
  3. Stelle sicher, dass der Client SNI sendet (das -servername oben): Ohne SNI liefern manche Endpunkte ein anderes Zertifikat, was zu Hostname-Mismatch-Fehlern führt.

Hängt der Handshake, statt fehlzuschlagen — besonders im VPN —, tippe auf ein MTU-Problem: Kleine Pakete kommen durch, die große Zertifikatsnachricht wird verworfen. Ein Test mit kleinerer MTU auf dem Interface bestätigt das. TLS-Fehler allgemein behandelt MQTT TLS handshake failed.

Die ganze Kette mit einem Skript prüfen

Dieses Skript (Python 3.8+, paho-mqtt 2.x) testet jede Schicht der Reihe nach, stoppt beim ersten Fehler und gibt die Dauer jedes Schritts aus:

netcheck.py
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}")

Ein gesunder Lauf gibt vier OK-Zeilen aus. Ein Fehler nennt dir die Schicht und die genaue Exception, die direkt zur Tabelle am Anfang dieses Artikels passt. Führe das Skript auf der Maschine aus, die das Problem hat — ein Laptop in einem anderen Netz beweist nichts über das Gerät, das scheitert.

Die Lösung bestätigen

Nachdem du DNS, Firewall-Regeln oder Proxy-Einstellungen geändert hast, prüfe Ende-zu-Ende, statt der Änderung einfach zu vertrauen:

  1. Führe netcheck.py auf der betroffenen Maschine erneut aus und bestätige, dass alle vier Schichten bestehen.
  2. Abonniere ein Test-Topic im Online-Client und publiziere vom betroffenen Gerät darauf.
  3. Lass die Verbindung länger inaktiv als das vermutete Firewall-Timeout und prüfe, ob weiterhin Nachrichten ankommen.

Online-Client öffnen und Zustellung testen

Netzwerkprobleme wirken zufällig, bis du sie in Schichten zerlegst. Namen auflösen, Socket öffnen, Zertifikat prüfen, dann MQTT sprechen — der erste Schritt, der scheitert, ist der, den du reparieren musst, und die Fehlermeldung nennt ihn meist schon.

Häufig gestellte Fragen

Warum funktioniert mein MQTT-Client zu Hause, aber nicht im Büro?

Firmennetze blockieren oft ausgehende Ports wie 1883 und 8883, erzwingen einen HTTP-Proxy oder inspizieren TLS. Teste jede Schicht aus dem Büronetz: DNS, eine rohe TCP-Verbindung, den Aussteller des TLS-Zertifikats und dann MQTT. MQTT über WebSockets auf Port 443 ist häufig der Ausweg.

Wie erkenne ich, ob eine Firewall MQTT-Traffic verwirft?

Eine Firewall, die Pakete verwirft, erzeugt einen Timeout (ETIMEDOUT, 'timed out'), während ein geschlossener Port auf einem erreichbaren Host sofort mit 'Connection refused' antwortet. Führe nc -vz oder Test-NetConnection gegen den Port aus und vergleiche mit einem anderen Port desselben Hosts.

Wie erkenne ich TLS-Interception in meinem Netzwerk?

Führe openssl s_client gegen den Broker aus und gib den Zertifikatsaussteller aus. Ist der Aussteller die CA deiner Firma oder eines Security-Produkts statt einer öffentlichen CA, wird die Verbindung abgefangen, und dein Client scheitert an der Zertifikatsprüfung, solange er dieser CA nicht vertraut.