MQTT steht für Message Queuing Telemetry Transport und ist ein offenes Nachrichtenprotokoll für Machine-to-Machine-Kommunikation. Es ermöglicht den Austausch von Nachrichten zwischen „Internet of Things“-Geräten. Für MQTT sind die Ports 1883 und 8883 reserviert.
Eclipse Mosquitto ist ein Open Source Message Broker (Server), der MQTT-Protokolle implementiert. Mit seiner guten Community-Unterstützung, Dokumentation und einfachen Installation wurde es zu einem der beliebtesten MQTT-Broker. Mosquitto kann wie jeder andere MQTT-Server („Broker“) als Zustands-Datenbank benutzt werden, da die gesamte Datenlage seiner Kommunikationspartner gehalten wird. Die MQTT-Geräte, die mit einem MQTT-Broker wie Mosquitto verbunden sind, nehmen nämlich nicht nur Befehle entgegen, sondern sammeln auch Daten ein.
In diesem Tutorial zeige ich dir, wie du Mosquitto installierst und den Mosquitto Broker so einrichtest, dass er SSL zum Schutz deiner passwortgeschützten MQTT-Kommunikation verwendet.
Installiere deinen Broker
Aktualisiere die Paketliste von Ubuntu mit folgendem Befehl in deinem Terminal
apt-get update && apt-get upgrade
und installiere den neuesten verfügbaren Mosquitto Broker, wonach der Service von Mosquitto starten wird.
apt-get install mosquitto
Als nächstes installierst du Mosquitto-Clients, indem du den unten aufgeführten Befehl ausführst.
apt-get install mosquitto-clients
Mosquitto-Clients ermöglicht dir MQTT problemlos über deine Konsole zu testen. Ich werde dir dies kurz an einem Beispiel zeigen. Hierzu werde ich zwei Terminals verwenden, eines zum Thema namens „test“ und eines zum Veröffentlichen einer Nachricht zum genannten Thema. Im ersten Terminal adressiere ich sozusagen eine Nachricht an das besagte Thema und im zweiten Terminal wird mir diese als Output ausgegeben.
Themen sind hierbei als Labels zu verstehen, die vom Mosquitto MQTT Broker zum Filtern von Nachrichten für jeden mit dem Server verbundenen Client verwendet werden. Diese können hierarchisch voneinander differenzierbar gemacht werden. Ein Client-Programm, das einem Thema wie z.B. Maintopic/Subtopic/… zugeordnet ist, wird nur Nachrichten erreichen, die von anderen Clients zum gleichen Thema veröffentlicht wurden.
Zum Nachvollziehen öffnest du einen zweiten Terminal und loggst dich dort erneut unter deinem Ubuntu-Server ein. Mit dem Kommando im unten gezeigten Code-Snippet empfängst du Nachrichten zu einem Thema. Da du Nachrichten entgegennehmen möchtest, beginnt der Befehl mit mosquitto_sub. Der Parameter -h hilft dabei den Host zu spezifizieren und der Parameter -t leitet die Definition des Themas ein. Den Platzhalter localhost kannst du mit der IP deines Servers austauschen, musst es aber nicht. Und den Platzhalter test könntest du mit einem x-beliebigen Thema wechseln.
mosquitto_sub -h localhost -t test
Nachdem du den oben präsentierten Befehl ausgeführt hast, erhältst du zunächst kein Output, sondern sorgst dafür, dass der Modus aufgerufen wird, in dem Nachrichten empfangen werden können.
Hiernach begibst du dich zurück in den ersten Terminal und lässt dabei den zweiten Terminal weiterhin im oben erzeugten Modus offen, da wir diesen für weitere Vorführeffekte nach der Passwort-Konfiguration im nächsten Kapitel benötigen. Im ersten Terminal gibst du dann das Kommando ein, das du dem Code-Snippet unten entnimmst. Da du nun eine Nachricht veröffentlichen möchtest, beginnt der Befehl mit mosquitto_pub. Die bereits bekannten Parameter werden um den Parameter -m erweitert, nach dem die Nachricht im String-Format folgt, die du veröffentlichen möchtest.
mosquitto_pub -h localhost -t test -m "Hello World!"
Nachdem du den obenstehenden Befehl ausgeführt hast, solltest du im zweiten Terminal das Hello World!-Output sehen. Im Screenshot unten habe ich dir dies mit Hilfe von Nummerierungen und der farblichen Punktmarkierung hervorgehoben.
Wenn du keine weiteren Nachrichten zum Thema test empfangen möchtest, kannst du im zweiten Terminal den Modus zum Erhalten von Nachrichten zum besagten Thema mit der Tastenkombination Strg+C beenden.
Sichere deinen Broker mit einem Passwort ab
Ich werde mit dir den Broker nun so konfigurieren, dass er Passwörter verwendet. Mosquitto beinhaltet eine Dienstleistung namens mosquitto_passwd, um eine spezielle Passwort-Datei zu generieren. Mit dem unten eingeblendeten Kommando, das mit mosquitto_passwd beginnt, ist es möglich, ein Passwort für den ebenfalls im Kommando angegebenen Benutzernamen testuser einzugeben und die Ergebnisse im Verzeichnis /etc/mosquitto/passwd zu speichern. Den Benutzernamen testuser kannst du nach Belieben im Kommando in deinem Terminal austauschen.
mosquitto_passwd -c /etc/mosquitto/passwd testuser
Im Anschluss daran erstellst du eine neue Konfigurationsdatei für Mosquitto, indem du diese via Terminal im Editor deiner Wahl öffnest. Ich nutze hierfür den nano-Editor. Mit dem Kommando im Code-Snippet unten würdest du diese Datei im nano-Editor öffnen.
nano /etc/mosquitto/conf.d/default.conf
Der Inhalt der Datei ist zunächst leer, da sie neu ist. Sie wird benötigt, um zu definieren, dass für alle Verbindungen via dem Broker ein Login verlangt wird und wo die oben erwähnte Passwort-Datei abgelegt ist. Füge die zwei Zeilen Code, die du im Code-Block unten zur Verfügung gestellt bekommst, via Copy&Paste als Inhalt in die Datei ein. Danach speicherst du dies, indem du die Tastenkombination Strg+O betätigst, mit der Enter-Taste den daraufhin in einem weißen Balken eingeblendeten Dateinamen bestätigst und schließlich den Editor mit der Tastenkombination Strg+X wieder verlässt.
allow_anonymous false
password_file /etc/mosquitto/passwd
Daraufhin startest du Mosquitto in beiden Terminals via dem folgenden Befehl neu.
systemctl restart mosquitto
Solltest du den Modus zum Empfangen von Nachrichten zum Thema test im zweiten Terminal nun erneut mit dem unten gezeigten Kommando versuchen zu erzeugen, solltest du eine entsprechende Fehlermeldung erhalten, die dir mitteilt, dass du nicht autorisiert bist und die Verbindung nicht zustande kommt.
mosquitto_sub -h localhost -t test
Wenn du den Befehl allerdings mit den dir bekannten Benutzerdaten ausführst, wie unten gezeigt, sollte es funktionieren. Nach dem Parameter -u folgt ein Nutzername und nach -P das zum Nutzer gehörende Passwort, das im Kommando unten wie der testuser als Platzhalter anzusehen ist und durch deine persönlichen Angabe ausgewechselt werden würde.
mosquitto_sub -h localhost -t test -u testuser -P password
Sobald du dann im ersten Terminal via dem unten stehenden Kommando eine Nachricht wie z.B. „Hello World – Again!“ publizierst, solltest du im zweiten Terminal entsprechendes Output hierzu entnehmen können.
mosquitto_pub -h localhost -t "test" -m "Hello World - Again!" -u testuser -P password
Auch hier sind die Parameter -u und -P hinzugekommen. Hättest du das Kommando ohne diese Parameter und deren Werte ausgeführt, solltest du ebenfalls – wie zuvor beschrieben – eine Fehlermeldung erhalten.
Installiere und führe Certbot für Let’s Encrypt Zertifikate aus
Let’s Encrypt ist ein Service, der kostenlose SSL-Zertifikate über eine automatisierte API anbietet. Ubuntu enthält den offiziellen Client zur Kommunikation mit der API in seinem Standard-Repository. Sollte dein Ubuntu-Server unter der Version 16.04 laufen, dann wäre dieser Client im Sinne der SSL-Verschlüsselung von Mosquitto nicht up to date, da ein wichtiges Feature fehlt. Sollte dies zutreffen, dann wären die folgenden Inhalte dieses Kapitels für dich relevant, ansonsten, falls du mit Ubuntu 18.04 arbeitest, brauchst du die Anleitung dieses Kapitels nicht zu befolgen.
Zur Kompensierung des fehlenden Features installierst du den offiziellen Client von einem Ubuntu PPA (Personal Package Archive), also von einem alternativen Repository mit neuerer Software. Hierzu fügst du zuerst mit dem folgenden Befehl das Repository hinzu.
add-apt-repository ppa:certbot/certbot
Führe im Anschluss ein Update deines Ubuntu-Servers durch
apt-get update
und installiere Certbot.
apt-get install certbot
Adde zu deiner Firewall http-Verbindungen.
ufw allow http
Nun kannst du Certbot ausführen. Tausche hierbei im unten eingeblendeten Kommando Platzhalter DNSDomainname mit dem dir bekannten DNS Domainnamen deines Servers aus
certbot certonly --standalone --preferred-challenges http-01 -d DNSDomainname
Während der Ausführung des Befehls, wirst du aufgefordert, eine E-Mail-Adresse einzugeben und die Nutzungsbedingungen zu akzeptieren.
Nachdem die Zertifikate nun in deinem Besitz sind, musst du gewährleisten, dass Certbot sie automatisch erneuert, wenn sie ablaufen. Hierzu öffnest du die crontab-Datei im Editor deiner Wahl. Ich tue dies mit dem unten aufgeführten Befehl im nano-Editor.
nano crontab
Sobald die Datei im Editor geöffnet ist, trägst du den im Code-Snippet unten präsentierten Code via Copy&Paste ein, speicherst dies und verlässt den Editor.
15 3 * * * certbot renew --noninteractive --post-hook "systemctl restart mosquitto"
Aktiviere SSL-Verschlüsselung für deinen Broker
Die SSL-Verschlüsselung ist aktiviert, wenn Mosquitto weiß, wo die Let’s Encrypt-Zertifikate deines Ubuntu-Servers gespeichert sind. Dies muss vorab deinem Broker mitgeteilt werden. Öffne hierzu dieselbe Konfigurationsdatei, die ich bereits im vorherigen Kapitel zur Passwort-Absicherung mit Inhalt befüllt habe. Ich öffne die Datei im unten gezeigten Kommando erneut im nano-Editor.
nano /etc/mosquitto/conf.d/default.conf
Unterhalb der zwei bereits existierenden Zeilen fügst du via Copy&Paste als zusätzlichen Inhalt die Zeilen Code ein, wie du sie im folgenden Code-Block erkennst. Es werden hierbei zwei separate Listener-Blöcke eingebunden. Der erste, listener 1883 localhost, aktualisiert den Standard-MQTT-Listener an Port 1883 und bindet ihn lediglich an die localhost-Schnittstelle. Mit Port 1883 sind wir bisher verbunden, er ist standardmäßig unverschlüsselt.
Der zweite, nämlich listener 8883, richtet an Port 8883 einen verschlüsselten Listener ein. Dies ist der Standardport für MQTT + SSL. Die nächsten drei Zeilen, certfile, cafile und keyfile, verweisen Mosquitto auf die entsprechenden Let’s Encrypt Dateien, um die verschlüsselten Verbindungen einzurichten.
listener 1883 localhost
listener 8883
certfile /etc/letsencrypt/live/DNSDomainname/cert.pem
cafile /etc/letsencrypt/live/DNSDomainname/chain.pem
keyfile /etc/letsencrypt/live/DNSDomainname/privkey.pem
DNSDomainname steht – wie im vorherigen Kapitel – in den letzten drei Zeilen als Platzhalter für den DNS Domainname. Wenn du mit der Einbindung der neuen Inhalte in die Konfigurationsdatei fertig bist, speicherst du dies und verlässt den Editor. Führe im Anschluss daran sowohl in deinem ersten als auch in deinem zweiten geöffneten Terminal einen Neustart von Mosquitto durch
systemctl restart mosquitto
und update deine Firewall dahingehend, dass diese Verbindungen zum Port 8883 zulässt.
ufw allow 8883
Schließlich prüfst du, ob die eben durchgeführte SSL-Konfiguration nun auch greift, indem du zwischen den zwei geöffneten Terminals wieder eine Nachricht austauscht. Im zweiten Terminal würdest du den unten eingeblendeten Code ausführen, wobei du DNSDomainname auch hier mit dem dir bekannten DNS Domainname austauscht.
mosquitto_sub -h DNSDomainname -t test -p 8883 --capath /etc/ssl/certs/ -u testuser -P password
Im ersten Terminal publizierst du dann via dem folgenden Kommando erneut eine Nachricht, um diese im zweiten Terminal zu empfangen.
mosquitto_pub -h DNSDomainname -t test -m "Hello World! - SSL secured" -p 8883 --capath /etc/ssl/certs/ -u testuser -P password
In beiden Kommandos aktiviert der Part –capath /etc/ssl/certs/ SSL. Würdest du die Befehle mit localhost statt dem DNS Domainname durchführen, würdest du eine Fehlermeldung bekommen.
Aktiviere Websockets für deinen Broker
Um MQTT mit JavaScript innerhalb von Webbrowsern zu sprechen, wurde das Protokoll so angepasst, dass es über Standard-Websockets funktioniert. Dies ist optional und solltest du das zunächst nicht benötigen, brauchst du den Anleitungen in diesem Kapitel nicht zu folgen. Falls du Gebrauch von dieser Funktionalität machen möchtest, sind allerdings erneut zusätzliche Einträge in die Konfigurationsdatei nötig.
Öffne die Konfigurationsdatei
nano /etc/mosquitto/conf.d/default.conf
und füge den im Code-Snippet unten zur Verfügung gestellten Code unterhalb des bereits in der Datei existierenden Inhalts ein. Wie bei den Einträgen zur Aktivierung von SSL müsstest du auch dieses Mal den Platzhalter DNSDomainname mit dem dir bekannten DNS Domainnamen deines Servers austauschen.
listener 8083
protocol websockets
certfile /etc/letsencrypt/live/DNSDomainname/cert.pem
cafile /etc/letsencrypt/live/DNSDomainname/chain.pem
keyfile /etc/letsencrypt/live/DNSDomainname/privkey.pem
Speichere dies, verlasse den Editor und starte daraufhin Mosquitto neu.
systemctl restart mosquitto
Update schließlich noch deine Firewall, sodass Verbindungen zum Port 8083 möglich sind.
ufw allow 8083
Wie in den vorherigen Kapiteln vorgeführt, sind mosquitto_pub und mosquitto_sub die besten Optionen für Publish/Subscribe-Operationen auf Servern ohne GUI.
Um mit der Nutzung von MQTT via GUI besser vertraut zu werden, bieten dir diverse Open-Source Tools die Möglichkeit. Für die Umsetzung unter einem Linux-Server eignen sich u.a. MQTT.fx und mqtt-spy. Über den Web Browser bietet dir Chrome zudem die Apps Websocket Client und MQTTLens. Die folgenden Screenshots geben einen kurzen Einblick in die Nutzung von MQTTLens. Du hast dort die Möglichkeit beliebig viele Verbindungen zu erstellen. Im Screenshot unten siehst du das Interface hierzu, in dem per Default bereits einige Daten wie z.B. der Port eingetragen sind. Du kannst jeder Verbindung einen Namen geben. Als Hostname habe ich broker.mqttdashboard.com eingetragen.
Der Screenshot unten zeigt den Zustand, nachdem ich zwei Verbindungen angelegt habe, nämlich die Verbindungen testConnection-1 und testConnection-2. Via +-Icon kann ich jederzeit zusätzliche Verbindungen erzeugen.
Zwischen den Verbindungen, die im Sinne der “Maschine-zu-Maschine-Kommunikation” als zwei Maschinen betrachtet werden können, können nun Nachrichten ausgetauscht werden. Der unten präsentierte Screenshot zeigt dies gut. Dort gibt es das Thema testTopic, das ich in der Verbindung testConnection-2 mittels dem SUBSCRIBE-Button empfänglich für Nachrichten zu dem Thema testTopic gemacht habe, sowie das Thema testTopic, zu dem ich in der Verbindung testConnection-1 mittels dem PUBLISH-Button die Nachricht “Hello World!” veröffentlicht habe.
Gleichermaßen könnte ich von der Verbindung testConnection-2 zur Verbindung testConnection-1 Nachrichten versenden, entweder zum selben Themenkanal oder zu anderen Themen. Im Screenshot unten ist dies verbildlicht, wo nun zusätzlich zum Thema testTopic2 von testConnection-2 nach testConnection-1 eine Nachricht ausgetauscht wurde.
Fazit
Du weißt nun wie du dir einen SSL und Passwort geschützten Mosquitto MQTT Broker unter deinem Ubuntu Server installierst und konfigurierst. Ich habe dir in kleinen Beispielen die Funktionsweise des Brokers sowohl via Terminal eines Rechners als auch via einer der Browser gestützten Apps gezeigt. Weitere Informationen zum Mosquitto MQTT Broker und den Kommandoschnittstellen, wie z.B. mosquitto_pub und mosquitto_sub, bietet dir die online zugängliche Dokumentation zum Broker. Im Internet wirst du bei deiner Recherche zu dem Thema eine Menge weitere Hinweise, Applikationen und sogar programmierte Skripte finden, die dir zusätzliche Möglichkeiten zum Umgang und der Nutzbarkeit des Brokers nahe bringen, sodass du diesen in Zukunft vielleicht auch für eigene Projekte zum kommunikativen Austausch von „Internet of Things“-Geräten verwenden kannst.