MQTT-Sicherheit

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.

Illustration geschützter MQTT-Zugangsdaten auf Geräten, gespeichert in verschlüsseltem Flash und einem Secure Element auf einer Platine
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-Zugangsdaten auf Geräten zu schützen bedeutet, sicherzustellen, dass Benutzername und Passwort, mit denen Ihr Gerät den Broker erreicht, nicht aus Firmware-Images, ausgelesenen Flash-Chips, Debug-Schnittstellen oder Logdateien gelesen werden können. Dieser Leitfaden vergleicht die praktischen Optionen auf ESP32- und Linux-Geräten, zeigt jeweils die Konfiguration und listet die Fehler auf, durch die Zugangsdaten im Feld am häufigsten durchsickern.

Das Bedrohungsmodell in einfachen Worten

Bevor Sie eine Speichermethode wählen, sollten Sie klären, gegen wen Sie sich verteidigen:

Angreifer Zugriff Was er versucht
Jemand mit Ihrer Firmware-Datei Eine .bin von einer Download-Seite oder aus einem Support-Ticket Das Image nach Strings durchsuchen
Jemand mit einem Gerät Physischer Zugriff, ein USB-Seriell-Adapter Flash über UART auslesen, JTAG anschließen
Malware oder ein Bug auf dem Gerät Code, der auf dem Gerät läuft Dateien oder Speicher lesen
Jemand im Netzwerk Paketmitschnitt Das Passwort aus CONNECT lesen

Gegen den Angreifer im Netzwerk hilft TLS auf Port 8883 (oder 8084 für WebSockets), das jeder ConnectMQ-Broker mit einem Let's-Encrypt-Zertifikat unterstützt; MQTT-Authentifizierung mit Benutzername und Passwort erklärt, warum Zugangsdaten niemals über Port 1883 übertragen werden dürfen. Dieser Artikel konzentriert sich auf die anderen drei: den Schutz des Geheimnisses im Ruhezustand auf dem Gerät.

Regel null: Zugangsdaten gehören nicht in die Firmware

Ein #define MQTT_PASSWORD "..." im Quellcode landet im Firmware-Binary, in Ihrer Git-Historie, in CI-Logs und in jeder Kopie des Images. Ein strings firmware.bin | grep -i pass findet es in einem typischen Hobbyprojekt oft innerhalb von Sekunden. Die Firmware muss für jedes Gerät identisch sein, die Zugangsdaten müssen pro Gerät eindeutig sein. Halten Sie beides getrennt und schreiben Sie die Zugangsdaten bei der sicheren IoT-Geräte-Provisionierung in den Speicher.

Optionen auf dem ESP32

Unverschlüsseltes NVS (Basis, nicht sicher)

Die Non-Volatile-Storage-Bibliothek (oder der Arduino-Wrapper Preferences) speichert Schlüssel-Wert-Paare in einer Flash-Partition. Damit sind Zugangsdaten von der Firmware getrennt, was bereits eine Verbesserung ist, doch die Daten liegen unverschlüsselt vor. Wer den Flash-Chip auslesen kann, kann auch das Passwort lesen.

NVS-Verschlüsselung plus Flash-Verschlüsselung

ESP-IDF kann NVS-Partitionen verschlüsseln. Im klassischen Verfahren liegen die NVS-Schlüssel in einer eigenen Partition nvs_keys, die durch Flash-Verschlüsselung geschützt ist, deren Schlüssel wiederum in eFuses liegt, die Software nicht zurücklesen kann. Neuere Chips wie ESP32-S3 und ESP32-C3 unterstützen zusätzlich ein HMAC-basiertes Verfahren, das die NVS-Schlüssel aus einem eFuse-Schlüssel ableitet, ohne Partition nvs_keys.

Eine Partitionstabelle mit verschlüsselter Schlüsselpartition:

# Name,    Type, SubType,  Offset, Size,   Flags
nvs,       data, nvs,      ,       0x6000,
nvs_keys,  data, nvs_keys, ,       0x1000, encrypted
phy_init,  data, phy,      ,       0x1000,
factory,   app,  factory,  ,       1M,

Relevante Optionen in sdkconfig:

CONFIG_SECURE_FLASH_ENC_ENABLED=y
CONFIG_SECURE_FLASH_ENCRYPTION_MODE_RELEASE=y
CONFIG_NVS_ENCRYPTION=y
CONFIG_SECURE_BOOT=y
CONFIG_SECURE_BOOT_V2_ENABLED=y

Der Release-Modus ist entscheidend: Der Development-Modus lässt Wege offen, unverschlüsselte Images neu zu flashen, was den Zweck bei ausgelieferten Geräten zunichtemacht. Secure Boot ergänzt die Verschlüsselung, indem es keine Firmware ausführt, die Sie nicht signiert haben, sodass ein Angreifer keinen Code flashen kann, der die entschlüsselten Zugangsdaten ausliest und ausgibt. Beides brennt eFuses unumkehrbar, testen Sie daher zuerst auf Ersatzplatinen und folgen Sie Schritt für Schritt der Espressif-Dokumentation zur Flash-Verschlüsselung.

Das Lesen der Zugangsdaten in einem Arduino-Sketch auf dem ESP32 sieht gleich aus, ob NVS verschlüsselt ist oder nicht, und genau darum geht es: Der Schutz liegt unterhalb der API.

#include <Preferences.h>

struct MqttCreds { String user, pass, clientId; };

bool loadCreds(MqttCreds &c) {
  Preferences prefs;
  if (!prefs.begin("mqtt", true)) return false;   // schreibgeschützt
  c.user = prefs.getString("user", "");
  c.pass = prefs.getString("pass", "");
  c.clientId = prefs.getString("cid", "");
  prefs.end();
  return c.user.length() && c.pass.length() && c.clientId.length();
}

void logCreds(const MqttCreds &c) {
  // Identität protokollieren, niemals das Passwort
  Serial.printf("MQTT user=%s clientId=%s pass=<%u bytes>\n",
                c.user.c_str(), c.clientId.c_str(), c.pass.length());
}

Secure Elements

Ein Secure Element wie der ATECC608 von Microchip ist ein separater Chip, der Schlüssel speichert und kryptografische Operationen ausführt, ohne private Schlüssel jemals herauszugeben. Am stärksten ist er bei zertifikatsbasierter Identität, bei der der private Schlüssel für Mutual TLS den Chip nie verlässt. Bei Passwort-Authentifizierung kann ein Secure Element dennoch helfen, indem es den Schlüssel hält, mit dem der Passwort-Blob im Flash verschlüsselt ist, und so die Hürde für physisches Auslesen erhöht. Es verursacht zusätzliche Stücklistenkosten, Platinenfläche und Treiberintegration und findet sich daher vor allem in Produkten mit hochwertigen Daten oder regulatorischem Druck, etwa durch den EU Cyber Resilience Act oder die Komponentenanforderungen von IEC 62443-4-2 für Geräte in Industrieanlagen.

Optionen auf Linux-Geräten

Gateways und Edge-Computer mit Linux, etwa das IIoT-Gateway neben der SPS im Schaltschrank, bieten umfangreichere Werkzeuge.

Dateiberechtigungen (Basis)

Speichern Sie Zugangsdaten außerhalb des Anwendungsverzeichnisses in einer Datei, die nur das Dienstkonto lesen kann:

sudo install -d -m 0700 -o mqttsvc -g mqttsvc /etc/mqtt-agent
sudo install -m 0600 -o mqttsvc -g mqttsvc credentials.env /etc/mqtt-agent/credentials.env

Das schützt vor anderen Benutzern und Diensten, nicht aber vor jemandem, der die SD-Karte entnimmt. Kombinieren Sie es für physischen Schutz mit vollständiger Festplattenverschlüsselung.

Verschlüsselte systemd-Credentials mit TPM

Auf Systemen mit systemd und einem TPM-2.0-Chip verschlüsselt systemd-creds ein Geheimnis so, dass es nur auf dieser Maschine und nur für den Dienst entschlüsselt werden kann, der es deklariert:

# Passwort verschlüsseln, gebunden an das TPM dieser Maschine
echo -n 'YOUR_PASSWORD' | sudo systemd-creds encrypt --with-key=tpm2 \
  --name=mqtt-password - /etc/credstore.encrypted/mqtt-password
# /etc/systemd/system/mqtt-agent.service
[Unit]
Description=MQTT telemetry agent
After=network-online.target
Wants=network-online.target

[Service]
User=mqttsvc
LoadCredentialEncrypted=mqtt-password:/etc/credstore.encrypted/mqtt-password
Environment=MQTT_USERNAME=YOUR_USERNAME MQTT_CLIENT_ID=YOUR_CLIENT_ID
ExecStart=/usr/bin/python3 /opt/mqtt-agent/agent.py
Restart=on-failure
RestartSec=10

[Install]
WantedBy=multi-user.target

Der Dienst liest das entschlüsselte Geheimnis aus einem privaten Verzeichnis im Arbeitsspeicher:

import os
import ssl
import paho.mqtt.client as mqtt

cred_dir = os.environ["CREDENTIALS_DIRECTORY"]
with open(os.path.join(cred_dir, "mqtt-password")) as f:
    password = f.read().strip()

client = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2,
                     client_id=os.environ["MQTT_CLIENT_ID"],
                     protocol=mqtt.MQTTv5)
client.username_pw_set(os.environ["MQTT_USERNAME"], password)
client.tls_set(cert_reqs=ssl.CERT_REQUIRED)
client.connect("YOUR_BROKER_HOST", 8883, keepalive=60)
client.loop_forever()

Ein kopiertes Festplatten-Image ist auf einer anderen Maschine wertlos, weil das TPM die Zugangsdaten dort nicht entsiegelt.

Speicheroptionen im Vergleich

Methode Plattform Schützt vor Firmware-Leaks Schützt vor Flash-Dump Aufwand
Fest in der Firmware Beliebig Nein Nein Keiner
Unverschlüsseltes NVS / Konfigurationsdatei ESP32 / Linux Ja Nein Gering
NVS-Verschlüsselung plus Flash-Verschlüsselung, Secure Boot ESP32 Ja Ja Mittel, unumkehrbare eFuses
Secure Element ESP32, Linux Ja Ja, am stärksten für Schlüssel Hoch
Dateiberechtigungen plus Festplattenverschlüsselung Linux Ja Teilweise Gering bis mittel
systemd-creds mit TPM Linux Ja Ja Mittel

Zugangsdaten im Arbeitsspeicher, in Backups und bei Updates

Verschlüsselter Speicher schützt die Zugangsdaten im Ruhezustand, doch sie müssen trotzdem in den RAM entschlüsselt werden, um das CONNECT-Paket zu bauen. Einige Gewohnheiten verringern das Risiko auf dem restlichen Weg:

  • An einer Stelle halten. Laden Sie die Zugangsdaten einmal in einen einzigen Puffer, der dem MQTT-Modul gehört, statt sie in globale Strings, Konfigurationsstrukturen und Diagnoseobjekte zu kopieren.
  • Aus Diagnosedaten ausschließen. Core Dumps, Absturzberichte und Remote-Log-Uploads dürfen niemals den Speicher mit den Zugangsdaten enthalten. Halten Sie unter Linux die Datei mit den Zugangsdaten aus Backup-Sätzen und Support-Bundles heraus.
  • Nicht über die Cloud hin- und herschicken. Eine Funktion zur Konfigurationssynchronisation, die die Geräteeinstellungen in Ihr Backend hochlädt, sollte die Felder mit Zugangsdaten vollständig auslassen.
  • Updates atomar schreiben. Wenn bei einer Rotation neue Zugangsdaten eintreffen, schreiben Sie sie in einen zweiten Slot und schalten Sie erst nach erfolgreicher Verbindung um, damit ein Stromausfall das Gerät nicht mit einem halb geschriebenen Passwort zurücklässt.
  • Bei der Außerbetriebnahme löschen. Löschen Sie den NVS-Namespace oder die Datei mit den Zugangsdaten im Rahmen von Werksreset und Außerbetriebnahme.

Fehler, durch die Zugangsdaten durchsickern

  1. Das Passwort in Debug-Logs oder Crash Dumps ausgeben.
  2. Es „der Bequemlichkeit halber" auf einer Geräte-Webseite anzeigen, selbst maskiert im HTML.
  3. Es in einer Retained Message speichern oder an ein gemeinsam genutztes Topic senden.
  4. UART-Download-Modus und JTAG auf Seriengeräten aktiviert lassen.
  5. Dieselben Zugangsdaten für die ganze Flotte verwenden, sodass ein einziges Auslesen alles kompromittiert.
  6. Nie rotieren, sodass Zugangsdaten, die vor Jahren geleakt wurden, immer noch funktionieren.

Punkt 5 verdient besondere Betonung. Bei ConnectMQ ist jede Client ID an die für sie ausgestellten Zugangsdaten gebunden, geben Sie also jedem Gerät einen eigenen Satz; ein ausgelesenes Passwort legt dann nur ein Gerät offen, das Sie mit dem Verfahren aus MQTT-Zugangsdaten rotieren widerrufen und ersetzen können. Dank Mandantenisolation erreichen selbst die Zugangsdaten eines kompromittierten Geräts nur Ihren eigenen Broker, und die IP-Sperre nach wiederholten fehlgeschlagenen Logins bremst Angreifer, die andere Passwörter erraten wollen. Die weiteren Maßnahmen behandelt der Artikel Best Practices für MQTT-Sicherheit.

Starten Sie mit ConnectMQ

Kombinieren Sie geschützten Speicher auf dem Gerät mit einem verwalteten MQTT-Broker, der TLS und die Ausstellung von Zugangsdaten für Sie übernimmt. Erstellen Sie unter app.connectmq.com einen kostenlosen Serverless-Broker, ganz ohne Kreditkarte, und testen Sie die Speicherung Ihrer Zugangsdaten auf ESP32 oder Linux gegen einen echten TLS-Endpunkt. Wenn Sie neu auf der Hardware-Seite sind, ist das ESP32-MQTT-Tutorial ein guter Einstieg, und der Leitfaden zum Cloud-MQTT-Broker erklärt die Hosting-Optionen.

Häufig gestellte Fragen

Ist die ESP32-Bibliothek Preferences sicher für MQTT-Passwörter?

Nur wenn NVS-Verschlüsselung und Flash-Verschlüsselung aktiviert sind. Ohne sie speichert Preferences die Daten im Klartext im Flash, den jeder mit physischem Zugriff auslesen kann.

Brauche ich ein Secure Element für MQTT-Zugangsdaten?

Nicht immer. Verschlüsselter Speicher mit Flash-Verschlüsselung und Secure Boot reicht für viele Produkte aus; ein Secure Element ist vor allem bei zertifikatsbasierter Identität oder besonders schützenswerten Deployments wertvoll.

Wo sollte ein Linux-Gateway sein MQTT-Passwort speichern?

Mindestens in einer Datei mit Berechtigungen 0600, die dem Dienstkonto gehört. Wo ein TPM vorhanden ist, binden verschlüsselte systemd-Credentials das Geheimnis an diese Maschine.

Schützt TLS die auf dem Gerät gespeicherten Zugangsdaten?

Nein. TLS schützt Zugangsdaten bei der Übertragung. Der Schutz des Speichers ist eine separate Schicht, die Sie auf dem Gerät selbst brauchen.

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-Zugriffskontrolllisten (ACLs): Konzepte und Design

Was MQTT-Zugriffskontrolllisten sind, wie Broker wie Mosquitto Lese- und Schreibregeln auf Topic-Ebene ausdrücken, wie sich abgelehnte Operationen verhalten und wie Sie Topic-Namespaces so entwerfen, dass die Autorisierung einfach bleibt.

7 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.