Anleitungen

Mosquitto absichern: Passwörter, ACLs und TLS

Mosquitto Schritt für Schritt absichern: Passwortdatei mit mosquitto_passwd anlegen, Topics per ACL-Datei mit %u und %c einschränken und TLS auf Port 8883 aktivieren.

Aktualisiert · 8 Min. Lesezeit

Eine frische Mosquitto-2.x-Installation lehnt anonyme Remote-Clients ab – ein guter Anfang. Um sie wirklich zu nutzen, brauchst du aber drei Schichten: Authentifizierung (wer bist du?), Autorisierung (welche Topics darfst du anfassen?) und Verschlüsselung (kann jemand im Netz mitlesen?). In Mosquitto sind das die Passwortdatei, die ACL-Datei und ein TLS-Listener. Diese Anleitung richtet alle drei ein.

Wenn der Broker noch nicht installiert ist, beginne mit Mosquitto installieren oder Mosquitto in Docker betreiben. Die Pfade unten gehen von einer Linux-Paketinstallation aus; in Docker nutzt du /mosquitto/config/ statt /etc/mosquitto/.

1. Eine Passwortdatei mit mosquitto_passwd anlegen

mosquitto_passwd speichert Benutzernamen mit gesalzenen Passwort-Hashes (nie im Klartext). Lege die Datei mit dem ersten Benutzer an und füge dann weitere hinzu:

Benutzer anlegen
# -c creates a NEW file and overwrites any existing one — first user only
sudo mosquitto_passwd -c /etc/mosquitto/passwd alice

# add or update users (prompts for the password)
sudo mosquitto_passwd /etc/mosquitto/passwd sensor-01

# non-interactive, e.g. in provisioning scripts
sudo mosquitto_passwd -b /etc/mosquitto/passwd bob 'S3cure-pass'

# delete a user
sudo mosquitto_passwd -D /etc/mosquitto/passwd bob

Vermeide -b auf geteilten Rechnern: Das Passwort landet in deiner Shell-History und in der Prozessliste. Sperre die Datei so, dass nur der Broker sie lesen kann:

bash
sudo chown mosquitto:mosquitto /etc/mosquitto/passwd
sudo chmod 0700 /etc/mosquitto/passwd

Sag dem Broker jetzt, dass er sie nutzen soll:

/etc/mosquitto/conf.d/secure.conf
listener 1883
allow_anonymous false
password_file /etc/mosquitto/passwd
Testen
sudo systemctl restart mosquitto

# should fail with "not authorised"
mosquitto_pub -h localhost -t test -m hi

# should succeed
mosquitto_pub -h localhost -u alice -P 'your-password' -t test -m hi

2. Topics mit einer ACL-Datei einschränken

Mit einer Passwortdatei allein darf jeder authentifizierte Benutzer jedes Topic lesen und beschreiben. Eine ACL-Datei schränkt das ein. Sobald acl_file gesetzt ist, wird alles verweigert, was nicht ausdrücklich erlaubt ist.

/etc/mosquitto/acl
# --- pattern rules apply to every authenticated client ---
# each device may read and write only below its own username
pattern readwrite devices/%u/#
# each client may read its own command topic, keyed by client ID
pattern read commands/%c

# --- user-specific rules ---
user alice
topic readwrite #

user dashboard
topic read devices/#
topic write commands/+

user sensor-01
topic write telemetry/sensor-01/#
DirektiveBedeutung
user <name>Die folgenden topic-Zeilen gelten für diesen Benutzernamen
topic [read|write|readwrite|deny] <filter>Gewährt (oder mit deny sperrt) den Zugriff; Wildcards + und # sind erlaubt. Ohne Angabe des Zugriffstyps gilt readwrite
pattern [access] <filter>Gilt für alle Clients; %u wird durch den Benutzernamen ersetzt, %c durch die Client-ID

Aktiviere sie neben der Passwortdatei:

/etc/mosquitto/conf.d/secure.conf
listener 1883
allow_anonymous false
password_file /etc/mosquitto/passwd
acl_file /etc/mosquitto/acl

Zwei Verhaltensweisen erwischen viele. Erstens wird ein Publish auf ein verbotenes Topic in MQTT 3.1.1 stillschweigend verworfen – der Client sieht keinen Fehler (MQTT-5-Clients bekommen bei QoS 1/2 einen Reason Code im PUBACK). Zweitens wird eine verbotene Subscription im SUBACK abgelehnt, was viele Client-Bibliotheken nicht anzeigen. Wenn „Nachrichten einfach nicht ankommen“, prüfe zuerst die ACL und lass den Broker beim Debuggen mit log_type all laufen. Mit dem Topic-Matcher prüfst du, welche Topics ein Filter wie devices/+/# wirklich abdeckt.

3. Traffic mit TLS verschlüsseln

Ohne TLS gehen Benutzernamen, Passwörter und Payloads im Klartext durchs Netz. Konvention ist MQTT über TLS auf Port 8883 (siehe MQTT-Ports). Du brauchst ein Zertifikat, den zugehörigen privaten Schlüssel und – bei selbstsignierten Setups – das CA-Zertifikat.

/etc/mosquitto/conf.d/tls.conf
# MQTT over TLS
listener 8883
certfile /etc/mosquitto/certs/server.crt
keyfile  /etc/mosquitto/certs/server.key
# cafile is only needed for self-signed / private CA chains or client certificates
# cafile /etc/mosquitto/certs/ca.crt

# Secure WebSockets for browser clients
listener 8884
protocol websockets
certfile /etc/mosquitto/certs/server.crt
keyfile  /etc/mosquitto/certs/server.key

Sobald TLS funktioniert, entferne den unverschlüsselten listener 1883 oder schirme ihn per Firewall ab (bzw. binde ihn mit listener 1883 127.0.0.1 an localhost), damit darüber keine Zugangsdaten durchsickern. Um Client-Zertifikate zu verlangen (Mutual TLS), ergänze am Listener cafile und require_certificate true; mit use_identity_as_username true wird der CN des Zertifikats für die ACL zum Benutzernamen.

Teste von einem Client aus:

bash
# public CA (e.g. Let's Encrypt): use the system trust store
mosquitto_sub -h mqtt.example.com -p 8883 --capath /etc/ssl/certs \
  -u alice -P 'your-password' -t 'devices/#' -v

# self-signed / private CA
mosquitto_sub -h mqtt.example.com -p 8883 --cafile ca.crt \
  -u alice -P 'your-password' -t 'devices/#' -v

Der Hostname in -h muss zu CN/SAN des Zertifikats passen, sonst schlägt die Prüfung fehl. Weitere CLI-Optionen findest du im Cheat Sheet zu mosquitto_pub/sub.

Ein Let's-Encrypt-Zertifikat nutzen

Mit einem öffentlich vertrauenswürdigen Zertifikat brauchen Clients keine eigene CA-Datei. Hol dir mit certbot eins für den Hostnamen deines Brokers (Port 80 muss für die HTTP-Challenge erreichbar sein) und lass Mosquitto dann auf die Live-Dateien zeigen:

ini
listener 8883
certfile /etc/letsencrypt/live/mqtt.example.com/fullchain.pem
keyfile  /etc/letsencrypt/live/mqtt.example.com/privkey.pem
  • Nutze fullchain.pem, nicht cert.pem – Clients brauchen das Zwischenzertifikat.
  • Der Benutzer mosquitto muss den Schlüssel lesen können; standardmäßig ist /etc/letsencrypt nur für root zugänglich. Viele Setups kopieren die Dateien per certbot-Deploy-Hook nach /etc/mosquitto/certs/ und setzen dort den Besitzer.
  • Zertifikate werden alle paar Monate erneuert. Ergänze systemctl reload mosquitto im Deploy-Hook, damit der Broker das neue Zertifikat übernimmt.

Alles zusammen

/etc/mosquitto/conf.d/secure.conf
listener 1883 127.0.0.1

listener 8883
certfile /etc/mosquitto/certs/fullchain.pem
keyfile  /etc/mosquitto/certs/privkey.pem

listener 8884
protocol websockets
certfile /etc/mosquitto/certs/fullchain.pem
keyfile  /etc/mosquitto/certs/privkey.pem

allow_anonymous false
password_file /etc/mosquitto/passwd
acl_file /etc/mosquitto/acl

Statt von Hand zu editieren, kannst du das mit dem mosquitto.conf-Generator erzeugen. Für das große Ganze – Client-ID-Richtlinien, Rate Limits, Monitoring – lies die MQTT-Security-Best-Practices, und wenn Clients mit „not authorised“ scheitern, erklärt der Leitfaden zu Verbindungsfehlern jeden Code.

Häufig gestellte Fragen

Wie lade ich die Mosquitto-Passwortdatei ohne Neustart neu?

Schick dem Broker ein SIGHUP, zum Beispiel mit sudo systemctl reload mosquitto oder kill -HUP mit der PID des Brokers. Mosquitto liest bei SIGHUP Passwort- und ACL-Datei neu ein, bestehende Clients bleiben verbunden.

Was bedeutet %u in einer Mosquitto-ACL-Datei?

In einer pattern-Zeile wird %u durch den Benutzernamen des verbindenden Clients ersetzt und %c durch seine Client-ID. Mit pattern readwrite devices/%u/# darf jeder Benutzer nur auf die Topics unter seinem eigenen Namen zugreifen.

Kann Mosquitto ein Let’s-Encrypt-Zertifikat nutzen?

Ja. Lass certfile auf fullchain.pem und keyfile auf privkey.pem zeigen, stelle sicher, dass der Benutzer mosquitto sie lesen kann, und lade den Broker nach jeder Erneuerung neu. Clients prüfen den Server dann mit dem CA-Store des Systems.