MQTT-Sicherheit

MQTT-Rate-Limiting und DoS-Schutz erklärt

Wie sich MQTT-Broker gegen Verbindungsfluten, Publish-Stürme und übergroße Payloads verteidigen, welche Limits ein verwalteter MQTT-Broker anwendet und wie Sie Clients schreiben, die diese Limits respektieren.

Diagramm zum MQTT-Rate-Limiting mit einem Broker, der einen Publish-Sturm drosselt, während normale IoT-Geräte weiter Nachrichten senden
Probieren Sie es auf Ihrem eigenen MQTT-Broker ausHolen Sie sich im Free-Tarif einen privaten, verwalteten MQTT-Broker und starten Sie mit fertigen Codebeispielen.
Kostenlos testen Codebeispiele Keine Kreditkarte erforderlich

MQTT-Rate-Limiting ist die Art, wie ein Broker sich selbst und seine Nutzer vor Clients schützt, die zu viel, zu schnell oder zu Großes senden. Dieser Artikel erklärt die wichtigsten Denial-of-Service-Muster bei MQTT, die Limits, die Broker dagegen einsetzen, wie ConnectMQ Quotas und Flood Protection anwendet und wie Sie Clients schreiben, die sich zurücknehmen, statt das Problem zu verschärfen. Die meisten Rate-Limit-Vorfälle werden eher durch fehlerhafte Firmware als durch Angreifer verursacht, daher zählen beide Seiten.

Warum MQTT Rate Limiting braucht

Ein MQTT-Broker ist eine gemeinsam genutzte Ressource. Jede Verbindung kostet Speicher, jede Nachricht kostet CPU und Bandbreite, und jede Subscription erhöht den Routing-Aufwand. Ohne Limits kann ein einziger fehlerhafter Client den Dienst für alle anderen Clients auf demselben Broker beeinträchtigen.

Die Bedrohung ist nicht nur böswillig. Häufige Ursachen für Überlast sind:

  • Ein Firmware-Bug, der in einer engen Schleife publiziert statt einmal pro Minute.
  • Ein Edge-Gateway, das jeden SPS-Zyklus (etwa alle 10 ms) als eigene Nachricht publiziert, statt Werte zu aggregieren oder nur Änderungen zu senden.
  • Eine Reconnect-Schleife ohne Verzögerung nach einer Netzwerkstörung, wiederholt in einer ganzen Flotte.
  • Eine Kamera oder ein Logger, der versehentlich große Binärblöcke publiziert.
  • Ein Dashboard, das auf einem stark ausgelasteten Broker # abonniert und jede Nachricht verteilt.
  • Das Erraten von Zugangsdaten, das eine Verbindung nach der anderen öffnet.

Rate Limiting macht aus diesen Fehlern statt Ausfällen eingegrenzte, sichtbare Fehlermeldungen.

Die wichtigsten DoS-Muster bei MQTT

Muster Was passiert Typische Abwehr
Verbindungsflut Viele TCP-/TLS-Verbindungen werden schnell geöffnet, jede kostet einen Handshake und Speicher Verbindungsratenlimits pro IP, maximale Verbindungen pro Mandant, IP-Sperre
Reconnect-Sturm Tausende Geräte verbinden sich nach einem Ausfall im selben Moment neu Clientseitiges exponentielles Backoff mit Jitter
Publish-Sturm Ein Client sendet weit mehr Nachrichten pro Sekunde als erwartet Nachrichtenratenlimits pro Client, Trennung bei Missbrauch
Übergroße Payloads Riesige Nachrichten verbrauchen Speicher und Bandbreite Maximale Paketgröße
Subscription-Explosion Ein Client legt viele Subscriptions oder breite Wildcards an Maximale Subscriptions pro Client, Limits für die Topic-Tiefe
Aufgeblähte Retained Messages oder Sessions Viele Retained-Topics oder langlebige Sessions mit gepufferten Nachrichten Limits für Retained Messages, Session Expiry
Langsame Konsumenten Subscriber, die nicht mithalten, lassen Warteschlangen wachsen Queue-Limits, QoS-Wahl, Message Expiry
Erraten von Zugangsdaten Wiederholte fehlgeschlagene Logins Drosselung fehlgeschlagener Logins und IP-Sperre

Wie Broker Limits durchsetzen

Limits auf Verbindungsebene

Am günstigsten lässt sich Missbrauch stoppen, bevor ein Client authentifiziert ist. Broker begrenzen, wie viele Verbindungen eine einzelne IP pro Sekunde öffnen darf, deckeln die Gesamtzahl der Verbindungen pro Konto oder Plan und sperren Quellen, die wiederholt an der Authentifizierung scheitern. Ein TLS-Handshake ist relativ teuer, daher schützt die Drosselung in dieser Phase CPU und Speicher gleichermaßen.

Limits auf Nachrichtenebene

Nach dem Verbindungsaufbau kann der Broker Nachrichten pro Sekunde und Bytes pro Sekunde pro Client verfolgen. Überschreitet ein Client sein Budget, hat der Broker einige Optionen: die Verarbeitung verzögern, Nachrichten verwerfen, sie mit einem Reason Code ablehnen oder den Client trennen. MQTT 5 macht das wesentlich transparenter als MQTT 3.1.1.

Limits für die Paketgröße

Jeder Broker hat eine maximale Paketgröße. MQTT 5 erlaubt beiden Seiten, sie anzukündigen: Der Broker sendet Maximum Packet Size im CONNACK, und Clients sollten nie mehr senden. Eine Nachricht über dem Limit ist ein Protokollfehler und führt in der Regel zur Trennung.

Limits für Subscriptions und Topics

Obergrenzen für Subscriptions pro Client und für die Topic-Tiefe verhindern, dass Clients unbegrenzten Routing-Aufwand erzeugen.

Hilfreiche Funktionen von MQTT 5

MQTT 5 hat mehrere Mechanismen eingeführt, die Limits explizit statt rätselhaft machen. Die Übersicht der Funktionen von MQTT 5 behandelt sie ausführlicher.

  • Reason Codes. Ein Broker kann auf ein PUBACK oder DISCONNECT mit 0x97 Quota exceeded oder 0x96 Message rate too high antworten, statt Daten stillschweigend zu verwerfen. Clients können den Grund protokollieren und langsamer werden.
  • Receive Maximum. Beide Seiten kündigen an, wie viele unbestätigte QoS-1- und QoS-2-Nachrichten sie gleichzeitig annehmen, was eine einfache Flusssteuerung ermöglicht.
  • Maximum Packet Size. Wird in CONNECT und CONNACK angekündigt, sodass übergroße Nachrichten vermieden statt abgelehnt werden.
  • Message Expiry. Alte Nachrichten werden verworfen, statt sich für Offline-Subscriber anzustauen.
  • Session Expiry. Verwaiste Sessions werden automatisch aufgeräumt.
  • Server Keep Alive. Der Broker kann das Keep-Alive-Intervall eines Clients überschreiben.

Mit MQTT 3.1.1 kann ein Broker, der Limits durchsetzt, meist nur Nachrichten verwerfen oder die Verbindung schließen, und der Client sieht einen generischen Netzwerkfehler.

Limits bei ConnectMQ

ConnectMQ wendet Limits auf mehreren Ebenen an, um die Mandanten auf seinen gemeinsam genutzten Clustern zu schützen:

  • Quotas pro Plan. Der kostenlose Serverless-Plan erlaubt bis zu 25 Verbindungen, QoS bis 1 und Nachrichten bis 256 KB. Der kostenpflichtige Serverless-Plan erhöht das auf bis zu 1.000 Verbindungen, QoS 2 und Nachrichten bis 1 MB. Dedicated- und BYOC-Deployments laufen auf isolierter Infrastruktur.
  • Signalisierung von Quotas. Wird eine Quota überschritten, erhalten MQTT-5-Clients den Reason Code 0x97 (quota exceeded), sodass Sie ein Limit von einem Netzwerkfehler unterscheiden können.
  • Flood Protection gegen missbräuchliche Verbindungs- und Nachrichtenmuster.
  • IP-Sperre nach wiederholten fehlgeschlagenen Logins.
  • Mandantenisolation, sodass der Traffic eines Mandanten die Topics eines anderen nicht erreichen kann.

Der öffentliche MQTT-Broker broker.connectmq.com hat strengere Limits pro Client, weil er für alle offen ist: 64 KB pro Nachricht, 10 Nachrichten pro Sekunde pro Client, 10 Subscriptions pro Client, 8 Topic-Ebenen und Session Expiry bis 30 Minuten. Wenn ein Test an diese Grenzen stößt, ist das ein deutlicher Hinweis, die Last auf einen privaten Broker zu verlagern. Der Artikel zum kostenlosen öffentlichen MQTT-Broker listet die Details auf.

Clients schreiben, die Limits respektieren

Serverseitige Limits sind nur die halbe Geschichte. Eine Flotte gut erzogener Clients ist der beste DoS-Schutz, den Sie haben können.

  1. Beim Reconnect zurückhalten. Nutzen Sie exponentielles Backoff mit zufälligem Jitter, damit sich Geräte nach einem Ausfall nicht im Gleichschritt neu verbinden.
  2. Bündeln und aggregieren. Senden Sie eine Nachricht mit zehn Messwerten statt zehn Nachrichten, wo die Latenz es erlaubt.
  3. Bei Änderung publizieren, nicht bei jedem Schleifendurchlauf. Fügen Sie Totbänder hinzu, damit kleinste Schwankungen keinen Traffic erzeugen. Dieses Prinzip (Report by Exception) ist auch in Sparkplug B und vielen Unified-Namespace-Architekturen in der Fertigung üblich.
  4. Die angekündigte Paketgröße respektieren. Lesen Sie Maximum Packet Size aus den CONNACK-Properties.
  5. Reason Codes behandeln. Protokollieren Sie 0x97 und 0x96 und senken Sie Ihre Publish-Rate, statt sofort erneut zu senden.
  6. Subscriptions eng halten. Abonnieren Sie die Topics, die Sie brauchen, nicht #.
  7. Eindeutige Client IDs verwenden. Zwei Geräte mit derselben ID werfen sich gegenseitig in einer Endlosschleife hinaus, die wie eine Flut aussieht.

Hier ein Python-Client mit paho-mqtt 2.x, der Backoff anwendet, Quota-Reason-Codes behandelt und sein eigenes Publizieren drosselt:

import json
import random
import time
import paho.mqtt.client as mqtt

HOST, PORT = "broker.connectmq.com", 8883
CLIENT_ID = f"rate-demo-{random.randint(1000, 9999)}"
TOPIC = f"connectmq/demo/{CLIENT_ID}/telemetry"
MAX_RATE = 2.0  # Nachrichten pro Sekunde, deutlich unter dem Limit des öffentlichen Brokers

client = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2, client_id=CLIENT_ID,
                     protocol=mqtt.MQTTv5)
client.tls_set()
# Für einen privaten Broker ergänzen: client.username_pw_set("YOUR_USERNAME", "YOUR_PASSWORD")
client.reconnect_delay_set(min_delay=1, max_delay=120)  # exponentielles Backoff

slow_down_until = 0.0

def on_connect(c, userdata, flags, reason_code, properties):
    print("connected:", reason_code)
    if properties and hasattr(properties, "MaximumPacketSize"):
        print("broker max packet size:", properties.MaximumPacketSize)

def on_publish(c, userdata, mid, reason_code, properties):
    global slow_down_until
    if reason_code.is_failure:
        print(f"publish {mid} refused: {reason_code}")
        if reason_code.value in (0x96, 0x97):
            slow_down_until = time.time() + 30  # 30 s pausieren

def on_disconnect(c, userdata, flags, reason_code, properties):
    print("disconnected:", reason_code)

client.on_connect = on_connect
client.on_publish = on_publish
client.on_disconnect = on_disconnect

client.connect(HOST, PORT, keepalive=60)
client.loop_start()

interval = 1.0 / MAX_RATE
try:
    while True:
        if time.time() < slow_down_until:
            time.sleep(1)
            continue
        payload = json.dumps({"t": round(20 + random.random(), 2), "ts": int(time.time())})
        client.publish(TOPIC, payload, qos=1)
        time.sleep(interval)
except KeyboardInterrupt:
    client.loop_stop()
    client.disconnect()

Dieselben Prinzipien gelten für Firmware. Bauen Sie auf einem ESP32 vor jedem Reconnect-Versuch eine Verzögerung mit Jitter ein und rufen Sie publish() nie ohne Timer aus einer Schleife auf; das ESP32-MQTT-Tutorial zeigt ein nicht blockierendes Muster.

Rate-Limit-Probleme überwachen

Achten Sie in Ihren Client-Logs und Broker-Dashboards auf diese Signale:

  • Spitzen bei Verbindungsabbrüchen über viele Geräte hinweg im selben Moment.
  • Wiederholte Reason Codes 0x97 oder 0x96 vom selben Client.
  • Geräte, die sich in einem Zyklus von wenigen Sekunden verbinden, publizieren und trennen.
  • Eine Nachrichtenrate, die nicht zum konfigurierten Meldeintervall passt.

Bei ConnectMQ helfen Ihnen das Dashboard im Portal und der Live-Topic-Explorer, einen geschwätzigen Client zu erkennen, und mit $SYS/broker/connection/{clientId}/state können Sie den Verbindungsstatus eines bestimmten Clients beobachten.

Wann ein größerer Plan sinnvoll ist

Wenn legitimer Traffic und kein Bug an Limits stößt, liegt die Lösung in mehr Kapazität statt in strengeren Clients. Anzeichen sind ein stetiges Wachstum verbundener Geräte, Bedarf an QoS 2 oder Payloads über 256 KB. Der Leitfaden zum verwalteten MQTT-Broker erklärt, wie sich Serverless- und Dedicated-Optionen unterscheiden, und der verwandte Artikel über offen erreichbare MQTT-Broker zeigt, warum selbst gehostete Broker ohne Limits ein Risiko sind.

Starten Sie mit ConnectMQ

Erstellen Sie unter app.connectmq.com einen Broker im kostenlosen Serverless-Plan, ganz ohne Kreditkarte, verbinden Sie den obigen Client mit Ihren generierten Zugangsdaten und sehen Sie, wie sich Quotas und Reason Codes in der Praxis verhalten. Weiterführende Hinweise finden Sie unter Best Practices für MQTT-Sicherheit.

Häufig gestellte Fragen

Was bedeutet der MQTT-Reason-Code 0x97?

Er bedeutet „Quota exceeded". Der Broker teilt dem Client mit, dass er ein erlaubtes Limit überschritten hat, daher sollte der Client langsamer werden, statt sofort erneut zu senden.

Unterstützt MQTT 3.1.1 Rückmeldungen zu Rate Limits?

Nicht direkt. MQTT 3.1.1 kennt keine Reason Codes im PUBACK, ein Broker kann also nur Nachrichten verwerfen oder trennen. Stellen Sie Clients auf MQTT 5 um, um explizite Rückmeldungen zu erhalten.

Sollte ich auch auf dem Gerät drosseln?

Ja. Clientseitige Drosselung, Bündelung und Reconnect-Backoff verhindern die meisten Vorfälle und halten Sie deutlich innerhalb der Broker-Limits.

Was ist ein Reconnect-Sturm?

Er entsteht, wenn viele Geräte gleichzeitig die Verbindung verlieren und alle sofort neu verbinden wollen. Exponentielles Backoff mit zufälligem Jitter verteilt die Neuverbindungen über die Zeit.

Verwandte Artikel

MQTT-Zugangsdaten ohne Ausfallzeit rotieren

Eine Schritt-für-Schritt-Strategie mit zwei parallelen Zugangsdaten, um MQTT-Benutzernamen und -Passwörter in einer Geräteflotte zu rotieren: neue Zugangsdaten bereitstellen, mit Fallback umschalten, prüfen und erst dann die alten widerrufen.

7 Min. Lesezeit

MQTT-Zugangsdaten sicher auf Embedded-Geräten speichern

Ein praxisnaher Vergleich der Möglichkeiten, MQTT-Benutzernamen und -Passwörter auf ESP32- und Linux-Geräten zu schützen, von verschlüsseltem NVS und Flash-Verschlüsselung bis zu Secure Elements und TPM-gestützten systemd-Credentials.

8 Min. Lesezeit

Alle Artikel →

Ihr privater MQTT-Broker ist nur wenige Klicks entfernt

Konto anlegen, Broker-Zugangsdaten erhalten und das erste Gerät verbinden — ohne Server, die installiert, gepatcht oder skaliert werden müssen.