When an MQTT client fails with a vague "connection failed", the cause is rarely MQTT itself. It is usually one of four layers underneath: DNS could not resolve the broker name, TCP could not reach the port, a proxy or firewall silently ate the connection, or TLS was intercepted and the certificate no longer matches. Testing those layers in order — DNS → TCP → TLS → MQTT — finds the broken one in a few minutes.
This guide gives you the exact command for each layer, the error messages each failure produces, and a Python script that runs the whole chain and tells you where it breaks.
Read the error message first
The error text already tells you which layer to look at. These are the strings people search for most:
| Error | Layer | Usual cause |
|---|---|---|
getaddrinfo ENOTFOUND broker.connectmq.com (Node.js) | DNS | Typo in host, no DNS server, split-horizon DNS |
[Errno -2] Name or service not known (Python, Linux) | DNS | Same as above |
[Errno 8] nodename nor servname provided, or not known (Python, macOS) | DNS | Same as above |
getaddrinfo EAI_AGAIN | DNS | Resolver unreachable or temporarily failing |
connect ETIMEDOUT / TimeoutError: timed out | TCP / firewall | Packets dropped on the way, wrong IP, blocked port |
connect ECONNREFUSED / [Errno 111] Connection refused | TCP | Host reachable, nothing listening on that port |
ECONNRESET right after connecting | Proxy / firewall | Middlebox killed the connection after inspecting it |
certificate verify failed: unable to get local issuer certificate | TLS | Missing CA bundle or TLS interception |
self signed certificate in certificate chain | TLS | Corporate proxy re-signing traffic |
If you already get a CONNACK with a reason code, the network is fine and the problem is authentication or configuration — look it up in the reason code reference.
Layer 1: DNS resolution
Check that the name resolves, and that it resolves to the same addresses everywhere:
dig +short broker.connectmq.com A
dig +short broker.connectmq.com AAAA
# Compare with a public resolver to spot split-horizon or stale records
dig +short broker.connectmq.com @1.1.1.1
# Windows
nslookup broker.connectmq.comWhat to look for:
- No answer — the name does not exist in this resolver. Check spelling, and whether a VPN or corporate DNS overrides external zones.
- Different answers from your resolver and a public one — split-horizon DNS, an old cached record after a broker migration, or a DNS filter returning a block-page IP.
- An AAAA record but no IPv6 route — the client tries IPv6 first and hangs until it falls back. See MQTT IPv6 issues.
Inside containers, DNS comes from the container runtime, not the host. Run the same dig inside the container (docker exec -it app sh) before you assume the host result applies.
Layer 2: TCP reachability and routing
Resolution works; now open a raw TCP connection to each MQTT port you might use:
nc -vz -w 5 broker.connectmq.com 1883 # MQTT over TCP
nc -vz -w 5 broker.connectmq.com 8883 # MQTT over TLS
nc -vz -w 5 broker.connectmq.com 8084 # MQTT over secure WebSocketsTest-NetConnection broker.connectmq.com -Port 8883The difference between a timeout and a refusal is the most useful signal in network debugging:
succeeded/TcpTestSucceeded : True— the path is open; move on to TLS.Connection refused— you reached the host, but nothing listens there. Wrong port, or the broker is down.- Hangs, then times out — something between you and the broker drops the packets. That is almost always a firewall.
To see where the packets stop, trace the route on the actual port, not with ICMP (which many networks treat differently):
sudo traceroute -T -p 8883 broker.connectmq.com # Linux
mtr --tcp --port 8883 broker.connectmq.com # if mtr is installedIf the trace dies at your own gateway or the first corporate hop, the block is local. If it dies far away, the problem is upstream or at the broker's edge. A full walkthrough of port checks is in test whether an MQTT port is open, and the standard port numbers are listed in MQTT ports.
Layer 3: Firewalls and proxies
Office, hotel and cloud networks often allow only HTTP(S) out, through an explicit proxy. MQTT clients do not read HTTP_PROXY by default, so the direct connection simply times out.
First, find out whether a proxy is configured:
env | grep -i _proxy
# Windows: netsh winhttp show proxyThen check whether the proxy will tunnel to the broker port with an HTTP CONNECT:
nc -X connect -x proxy.example.corp:3128 -vz broker.connectmq.com 8883If the proxy refuses CONNECT to 8883 but allows 443, you have two options: use MQTT over secure WebSockets on a port the proxy permits, or ask the network team to allow the broker host. Browser-based clients go through the system proxy automatically, which is why the online MQTT client often works on networks where a native client fails. More strategies are in MQTT behind a corporate firewall and MQTT over port 443.
Layer 4: TLS and interception
The TCP port is open, but TLS fails. Look at the certificate the client actually receives:
openssl s_client -connect broker.connectmq.com:8883 \
-servername broker.connectmq.com -showcerts </dev/null 2>/dev/null \
| openssl x509 -noout -subject -issuer -datesCompare the issuer line with what you get from a phone hotspot or home network. If the office shows an issuer such as your company name or a security vendor, a TLS-inspecting proxy is re-signing the connection. Your MQTT client rejects it with certificate verify failed or self signed certificate in certificate chain, which is correct behaviour.
Fixes, in order of preference:
- Ask for the broker host to be excluded from TLS inspection (MQTT is not HTTP, and many inspection products break it anyway).
- If policy requires inspection, add the corporate root CA to the client's trust store — never disable certificate verification.
- Make sure the client sends SNI (the
-servernameabove): without it some endpoints return a different certificate, which produces hostname mismatch errors.
If the handshake hangs instead of failing, especially on a VPN, suspect an MTU problem: small packets pass, but the large certificate message is dropped. Testing with a smaller MTU on the interface confirms it. TLS errors in general are covered in MQTT TLS handshake failed.
Run the whole chain with one script
This script (Python 3.8+, paho-mqtt 2.x) tests each layer in order and stops at the first failure, printing the timing of every step:
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}")A healthy run prints four OK lines. A failure tells you the layer and the exact exception, which maps directly to the table at the top of this article. Run it from the machine that has the problem — a laptop on a different network proves nothing about the device that fails.
Confirm the fix
After changing DNS, firewall rules or proxy settings, verify end to end rather than trusting the change:
- Re-run
netcheck.pyon the affected machine and confirm all four layers pass. - Subscribe to a test topic in the online client and publish to it from the affected device.
- Leave the connection idle for longer than the suspected firewall timeout and check that messages still arrive.
Open the online client to test delivery
Network problems feel random until you split them into layers. Resolve the name, open the socket, inspect the certificate, then speak MQTT — whichever step fails first is the one to fix, and the error message usually names it already.
Frequently asked questions
Why does my MQTT client work at home but not in the office?
Corporate networks usually block outbound ports such as 1883 and 8883, force traffic through an HTTP proxy or inspect TLS. Test each layer from the office network: DNS, a raw TCP connection, the TLS certificate issuer, then MQTT. WebSockets over port 443 is often the way through.
How can I tell whether a firewall is dropping MQTT traffic?
A firewall that drops packets produces a timeout (ETIMEDOUT, 'timed out'), while a closed port on a reachable host answers immediately with 'Connection refused'. Run nc -vz or Test-NetConnection against the port and compare with another port on the same host.
How do I detect TLS interception on my network?
Run openssl s_client against the broker and print the certificate issuer. If the issuer is your company's or a security product's CA instead of a public CA, the connection is being intercepted and your client will fail certificate verification unless it trusts that CA.

