Anleitungen

MQTT über WebSockets: Verbindung aus dem Browser

MQTT über WebSockets erklärt: warum Browser es brauchen, ws vs. wss, der Pfad /mqtt, gängige Ports, Mixed-Content-Fehler und ein Browser-Beispiel mit MQTT.js.

Aktualisiert · 7 Min. Lesezeit

MQTT läuft normalerweise über eine reine TCP-Verbindung auf Port 1883 (bzw. 8883 mit TLS). Browser können keine rohen TCP-Sockets öffnen, daher kann eine Web-App auf diesem Weg kein MQTT sprechen. Die Lösung heißt MQTT über WebSockets: dieselben MQTT-Pakete, transportiert in einer WebSocket-Verbindung, die jeder Browser unterstützt. Dieser Guide erklärt, wie das funktioniert und wie du die Fehler vermeidest, über die die meisten stolpern.

Warum Browser WebSockets brauchen

Aus Sicherheitsgründen darf JavaScript in einer Webseite Netzwerkverbindungen nur über Browser-APIs aufbauen – fetch, XMLHttpRequest, WebSocket, WebRTC und WebTransport. Keine davon kann eine beliebige TCP-Verbindung zu Port 1883 öffnen. WebSockets passen ideal zu MQTT, weil sie einen langlebigen, bidirektionalen, binären Kanal bieten – genau das, was MQTT braucht.

WebSockets sind nicht nur etwas für Browser. Sie helfen auch, wenn:

  • eine Firewall oder ein Unternehmens-Proxy nur Web-Traffic auf den Ports 80 und 443 durchlässt;
  • MQTT sich einen Load Balancer oder Reverse Proxy mit deinen HTTP-Services teilen soll;
  • du ein Dashboard, ein Admin-Tool oder eine mobile Web-App baust, die Live-Gerätedaten anzeigt.

So funktioniert MQTT über WebSockets

  1. Der Client öffnet eine HTTP(S)-Verbindung und sendet einen WebSocket-Upgrade-Request an eine URL wie wss://broker.emqx.io:8084/mqtt, wobei er das Subprotokoll mqtt anfordert.
  2. Der Broker antwortet mit 101 Switching Protocols, und die Verbindung wird zum WebSocket.
  3. Ab dann reisen MQTT-Pakete (CONNECT, PUBLISH, …) in binären WebSocket-Frames. Alles oberhalb des Transports – QoS, Retained Messages, Last Will, MQTT-5-Properties – funktioniert genau wie über TCP.

Auf dem Broker muss ein WebSocket-Listener aktiviert sein. Dieser läuft meist auf einem anderen Port als der TCP-Listener, und manche Broker erwarten einen bestimmten Pfad.

Eine praktische Konsequenz: Browser lassen JavaScript bei einem WebSocket-Request keine eigenen Header setzen. Die Authentifizierung findet deshalb normalerweise in MQTT selbst statt, über die Felder für Benutzername und Passwort im CONNECT-Paket, und nicht über HTTP-Header oder Cookies.

ws vs. wss

ws://wss://
VerschlüsselungKeine – Zugangsdaten und Payloads im KlartextTLS, wie bei HTTPS
Von HTTPS-Seiten nutzbarNein (als Mixed Content blockiert)Ja
Proxys und FirewallsWerden manchmal gestörtKommen auf Port 443 meist durch
Typischer EinsatzNur lokale EntwicklungAlles andere

Weil wss:// den TLS-Stack des Browsers nutzt, muss der Browser dem Zertifikat des Brokers vertrauen. Ein selbstsigniertes Zertifikat scheitert aus JavaScript heraus stillschweigend – öffne die URL https://host:port einmal in einem Tab, um den eigentlichen Zertifikatsfehler zu sehen.

Mixed Content: der häufigste Browser-Fehler

Wird deine Seite über https:// ausgeliefert (wie fast jede Website), blockiert der Browser jeden Versuch, eine ws://-Verbindung zu öffnen. Die Konsole zeigt einen Mixed-Content- oder Sicherheitsfehler, und der MQTT-Client verbindet sich einfach nie. Die Lösung ist immer dieselbe: Nutze den wss://-Endpunkt des Brokers. Unser Online-MQTT-Client wird aus genau diesem Grund über HTTPS ausgeliefert und verbindet sich nur über wss://.

Ports und Pfade

Einen einheitlichen Standard-WebSocket-Port für MQTT gibt es nicht; jeder Broker wählt seinen eigenen. Das sind die Endpunkte der öffentlichen Broker aus unserem Broker-Verzeichnis:

Brokerws://wss://Pfad
broker.hivemq.com80008884/mqtt
broker.emqx.io80838084/mqtt
test.mosquitto.org80808081beliebig
mqtt.eclipseprojects.io80443/mqtt

Ein falscher Pfad führt typischerweise zu einem fehlgeschlagenen Handshake (HTTP 404 oder eine geschlossene Verbindung), noch bevor MQTT überhaupt startet. Ein falscher Port endet meist in einem Timeout. Den vollständigen Überblick über TCP-, TLS- und WebSocket-Ports findest du unter MQTT-Ports erklärt.

Beispiel: MQTT im Browser mit MQTT.js

MQTT.js ist der meistgenutzte JavaScript-Client und funktioniert sowohl in Node.js als auch im Browser. Im Browser nutzt er automatisch WebSockets:

browser.js
import mqtt from 'mqtt';

const client = mqtt.connect('wss://broker.emqx.io:8084/mqtt', {
  clientId: `web-${crypto.randomUUID().slice(0, 8)}`,
  // username: 'user', password: 'secret',  // for private brokers
  reconnectPeriod: 2000,
});

client.on('connect', () => {
  client.subscribe('testmqtt/ws-demo/#');
  client.publish('testmqtt/ws-demo/hello', 'hello from the browser');
});

client.on('message', (topic, payload) => {
  console.log(topic, payload.toString());
});

client.on('error', (err) => console.error('MQTT error:', err.message));

WebSockets auf deinem eigenen Broker aktivieren

Wenn du deinen eigenen Broker betreibst, ist der WebSocket-Listener meist eine Sache von ein paar Konfigurationszeilen. In Mosquitto fügst du zum Beispiel neben dem TCP-Listener einen zweiten hinzu:

mosquitto.conf
listener 1883
protocol mqtt

listener 8080
protocol websockets

Für wss:// kannst du entweder Zertifikate direkt auf diesem Listener konfigurieren oder – häufiger – TLS an einem Reverse Proxy auf Port 443 terminieren und den unverschlüsselten WebSocket-Traffic an den Broker weiterleiten. Der Proxy braucht dafür aktivierte WebSocket-Unterstützung:

nginx-location-Block
location /mqtt {
    proxy_pass http://127.0.0.1:8080;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
    proxy_read_timeout 1h;
}

Achte darauf, dass das Read-Timeout des Proxys länger ist als dein MQTT-Keep-Alive-Intervall; sonst schließt der Proxy inaktive Verbindungen, und Clients erleben unerklärliche Disconnects.

Checkliste zur Fehlersuche

  • Port 1883 oder 8883 aus dem Browser? Das sind TCP-Ports – wechsle zum WebSocket-Listener.
  • Seite auf HTTPS, URL beginnt mit ws://? Mixed Content – nutze wss://.
  • Handshake scheitert sofort? Prüfe den Pfad (/mqtt oder keiner) und das Subprotokoll.
  • Hinter einem Reverse Proxy? Nginx und ähnliche Proxys müssen die Header Upgrade und Connection weiterleiten und langlebige Verbindungen erlauben.
  • Verbunden, aber wieder rausgeworfen? Das ist ein Problem auf MQTT-Ebene – siehe MQTT-Verbindungsfehler.

Jetzt eine wss://-Verbindung testen

Häufig gestellte Fragen

Warum kann sich mein Browser nicht über Port 1883 mit MQTT verbinden?

Browser können keine rohen TCP-Sockets öffnen, und auf Port 1883 läuft reines MQTT über TCP. Ein Browser-Client muss sich stattdessen mit dem WebSocket-Listener des Brokers verbinden – über eine ws://- oder wss://-URL mit dem richtigen Port und Pfad.

Was ist der Unterschied zwischen ws und wss bei MQTT?

ws:// ist eine unverschlüsselte WebSocket-Verbindung, wss:// ist WebSocket über TLS. Seiten, die über HTTPS ausgeliefert werden, dürfen nur wss:// verwenden, und für alles jenseits lokaler Tests ist wss:// die einzig sinnvolle Wahl.

Welchen Pfad sollte ich für MQTT über WebSockets verwenden?

Das hängt vom Broker ab. Viele Broker, darunter EMQX und HiveMQ, verwenden /mqtt. Mosquitto akzeptiert Verbindungen unabhängig vom Pfad. Prüfe die Dokumentation des Brokers; ein falscher Pfad scheitert meist schon beim WebSocket-Handshake.