Archiv für den Monat: Juni 2016

Mosquitto MQTT-Broker im Uberspace installieren

Vorbemerkung

Der ursprüngliche Artikel stammte vom 1. August 2015, etwas weniger als ein Jahr später hat sich die Sache allerdings weiterentwickelt, daher habe ich den Artikel umdatiert und neu veröffentlicht. Das Wichtigste zuerst: Die Sache funktioniert, sauber sicher und stabil. Der ganze nachfolgend erträumte Funktionsumfang ist noch nicht erreicht, aber daran kann man ja noch arbeiten.

Vision

Wir alle bewgen uns viel durch die Welt, häufig nicht alleine. Und Karten sind ein fantastisches Medium, um solche Bewegungen auf einer sphärischen Fläche festzuhalten und darzustellen. Zwei interessante Fragen/Problemstellungen/Aufgaben tauchen dabei häufiger auf:

  1. Wo bin ich überall schon mal gewesen?
  2. Wo bin ich jetzt grade, wohin bin ich unterwegs, wie bewege ich mich fort und wann komme ich an? (Insbesondere, wenn man sich mit jemandem treffen möchte)
  3. (Spielen! Jedes Mal, wenn ich über diesen Komplex nachdenke, drängt sich der Gedanke auf, dass man daraus ein fantastisches (Gelände-/Real-)Spiel basteln könnte, etwas in der Art einer Schnitzeljagd oder Geocaching in Verwandschaft zu Scotland Yard oder Mister X, vielleicht sogar mit Carmen Sandiego. Auch Deutschlandreise oder Globetrotter kommen einem in den Sinn. Große Metropolregionen wie das Ruhrgebiet, in dem ich wohne, bieten sich dafür natürlich an, aber auch im Rahmen einer Jugendfreizeit ließe sich das sicher gut nutzen. Siedler- oder andere Segelspiele haben wir ja schonmal auch ganz offline hinbekommen. Andere haben sowas auch schon gemacht: z.B. auf dem 31C3 und vorher wurde in der Freakshow davon berichtet. Ingress trifft einen ähnlichen Nerv)

Ziel wäre also, die Position von mehreren Leuten zu erfassen, verfolgen, aufzuzeichnen und (auch im Verlauf, also als Spur) darzustellen, eventuell in Beziehung zu setzen mit einander oder anderen Daten (Wetter, Verkehr, ÖPNV), zusätzlich noch Ziel/Zwischenziele, Route, Verkehrsmittel, Voraussichtliche Ankunftszeit, passende Wikipedia-Artikel etc.
Das würde erstmal die Grundanforderungen abdecken, sich mit anderen Menschen besser absprechen zu können und auch im Nachhinein sehen zu können, wo man war.
Wenn es dann noch zusätzlich Berechtigungs-Einschränkungen gäbe (alle senden ihre Position, aber nicht jeder kann immer die Positionen aller anderen einsehen), käme man der Spiel-Nutzung näher.

Möglichkeiten

Es gab mal einen Dienst namens Google Latitude, der ungefähr in die Richtung ging, er ist mittlerweile in Google+/Maps (Timeline) aufgegangen, in Facebook, FourSquare/Swarm, Apples Find My Friends oder waze finden sich ähnliche Ansätze. Sehr nah an meine Vorstellung der Umsetzung kommt Glympse, gegenüber den anderen genannten Diensten benötigt man zum Angucken kein Konto und die Freigabe ist zeitlich beschränkt.

Aber einen Nachteil haben sie alle: Sie sind ein großer Eingriff in die Privatsphäre, man gibt Kontrolle ab, man muss (überwiegend sehr großen) Firmen trauen, die im Ausland und damit anderen Jurisdiktionen sitzen, von denen man abhängig und denen man ausgeliefert ist. Kurz: Sie sind nicht  offen, noch frei.

Also sind sie keine echte Option. Ein paar gäbe es da aber schon schon: OsMo/OsmAnd, Userhash Location Reporting, Gps Cell Phone Tracker, Trackserver. Es gibt auch eine schöne Übersicht von Diensten mit Vergleich. So recht schien mir aber keins davon zu passen. Zwischenzeitlich trug ich mich mit dem Gedanken, selbst was auf reiner Browser/Javascript-Basis zu entwickeln, was eventuell mit einem NodeJS-Server spricht: Sehr viel Aufwand, aber wäre ein Anlass zum Lernen.

Ansatz

Doch in dem Vergleich wird OwnTracks erwähnt (nicht zu verwechseln mit owntrack, dessen Idee ähnlich, Umsetzung aber nicht so nachhaltig zu sein scheint), dazu gibt es auch einen Artikel bei Cashy und einen von nullniveau. (Und noch ein paar hier und dort). Das scheint mir eine Lösung voll nach meinem Geschmack. OwnTracks selbst ist eine OpenSource-App (sowohl für iOS als auch für Android), die die Position ermittelt und per MQTT (Message Queue Telemetry Transport), einem offenen Publish-/Subscribe-Protokoll für die dezentrale Übermittlung kleiner Nachrichten wie Sensor-Messdaten über Verbindungen, die auch schonmal aussetzen können, verteilt. Passt also sehr gut, hat auch den aparten Vorteil, dass die Server-Seite unabhängig von dem Geo-Thema ist und in der Heimautomatisierungsszene (s. openHAB) Zuspruch findet, man ist also da nicht allzusehr in der Nische und läuft Gefahr, dass man sich übernimmt oder die Weiterentwicklung eingestellt wird. Es gibt einen Open Source-MQTT Message Broker (=Server) namens Mosquitto, der auch von den OwnTracks-Machern unterstützt und empfohlen wird.

Einziger Wermutstropfen: OwnTracks ist zwar OpenSource, aber (noch) nicht im F-Droid-Repository zu finden, da es auf die proprietären Google Play Services zur Ortung zurückgreift. Kein Problem, das man nicht lösen könnte! 😉 (Allerdings ist die dafür notwendige Implementierung von Geofencing in LOST zur Zeit eingeschlafen.)

Die OwnTracks-App sendet und empfängt die Positionen und zeigt sie auf einer Karte an.
Der MQTT-Broker verteilt nur die Positions-Nachrichten aber zeichnet sie nicht auf, dazu gibt es mittlerweile ot-recorder (zuvor gab es schon das m2s-Backend bzw. auch mit Darstellung im Web den Nachfolger Pista. Um die Vision zu Erreichen, wäre außerdem der Einbau einer Authentifikation noch wichtig.

Mosquitto möchte ich gerne nicht auf einem Raspberry Pi installieren wie in der OwnTracks-Doku und allen anderen Anleitungen, die ich finden konnte, sondern in meinem Uberspace. Denn ich möchte die Position ja von Unterwegs aufzeichnen und einsehen, und ich möchte mein Netzwerk zuhause nicht nach Außen aufmachen. Das ist insofern problematisch, als die Anleitungen alle vom praktischen Weg “sudo apt-get” ausgehen, der im uberspace logischerweise nicht funktioniert (keine sudo-Berechtigung). Also bleibt nur die andere Möglichkeit: Selbst kompilieren.

Umsetzung

Genug der langen Vorrede, werden wir etwas konkreter und kommen zur Umsetzung: Den Mosquitto-Broker im Uberspace kompilieren und starten.

Eine der Anleitungen beinhaltet das Kompilieren, aber als root, von der bin ich ausgegangen und habe sie dann ein wenig angepasst, um der User-Umgebung Rechnung zu tragen. Außerdem werden jetzt in der zweiten Version des Artikels direkt von Anfang an Websockets mit aktiviert und in der Konfiguration TLS verwendet.

Los geht’s:

Websockets

Geholfen haben mir zwei Artikel.

libwebsockets 1.6 ist die letzte explizit von mosquitto erwähnte Version und danach haben sich ABI-Changes ereignet, also nehmen wir die und kompilieren/installieren sie:

Damit wird heruntergeladen, ausgepackt, das buildscript erzeugt und dann ausgeführt. Danach liegen in lib/  die nötigen libraries, die man nach ~/lib  kopieren kann:

Jetzt geht es weiter mit  mosquitto selbst.

Mosquitto

Nun muss die config.mk angepasst werden, um die Websockets-Bibliothek erreichbar zu machen und zu linken

Also Folgendes jeweils an den richtigen Stellen in der Datei ändern:

Dann ändern, speichern und verlassen.

Es werden außerdem noch zwei header-Dateien gebraucht:

Weiter mit

Dabei passiert folgendes: Die Dateien werden kompiliert und unter $HOME/ in  entsprechenden Verzeichnissen (~/bin, ~/include, ~/lib, ~/sbin, ~/share) abgelegt, aber am Ende des Kompilierens erscheint der Fehler

Man kann auch erkennen warum: Die Dateien, die eigentlich in /etc/mosquitto landen sollen, berücksichtigen aus unerklärlichen Gründen den Prefix nicht, und auf das systemweite /etc-Verzeichnis haben wir natürlich keinen Zugriff. Ist aber auch nicht weiter schlimm, wir legen einfach eine eigene Konfigurationsdatei an, sie wird gleich editiert:

TLS

Doch zunächst müssen noch einige Vorbereitungen bezüglich des TLS getroffen werden. Der Server soll unter einer eigenen Domain erreichbar sein und es soll ein Zertifikat von Let’s Encrypt zum Einsatz kommen, das passt gut in die Uberspace-Architektur und wird auf den Mobilgeräten automatisch akzeptiert. Alternativ, insbesondere wenn man keine Domain hat oder dafür nur die normale Uberspace-Domain ($USER.$SERVER.uberspace.de) benutzen möchte, wäre es auch möglich, das Zertifikat selbst zu generieren/signieren (Weiteres dazu unter http://owntracks.org/booklet/features/tls/ und http://mosquitto.org/man/mosquitto-tls-7.html) und das dazu passende CA-Zertifikat auf den Geräten in das System zu importieren oder in der App anzugeben. Das macht die Einrichtung aber unnötig kompliziert und hat z.B. bei Android als Nebeneffekt zur Folge, dass die Bildschirmsperre mindestens per Muster deaktiviert werden muss (was ohnehin eine gute Sache wäre).

Nun also –  Im virtuellen User-Webroot wird ein Verzeichnis als Platzhalter angelegt:

Es ist sinnvoll, hier eine eigene, sonst nicht benutzte Subdomain zu vergeben, (der Name muss natürlich entsprechend angepasst werden) um das Let’s Encrypt-Zertifikat separat zu verwalten.

Die (Sub-)Domain muss dann im DNS angelegt werden, z.B. bei INWX, was ich nur empfehlen kann. Im Wiki von Uberspace gibt es noch genauere Informationen.

Es muss sichergestellt sein, dass die Server von Let’s Encrypt unter der Domain auch wirklich den Uberspace-Server erreichen, also am besten nochmal von außen probieren, z.B. eine Test-Datei aus dem Platzhalter-Verzeichnis herunterzuladen.

Wenn Let’s Encrypt bisher noch nicht im Einsatz war ist es an der Zeit (den Uberspace-Wiki-Eintrag zu lesen und dann) für

Jetzt, oder falls Let’s Encrypt schon im Einsatz war findet sich unter ~/config/letsencrypt/cli.ini eine Konfigurationsdatei, in der alle Domains eingetragen sind. Die wird nun kopiert, bearbeitet (also alle Domains außer der für Mosquitto entfernt) und zum Erzeugen der Zertifikate benutzt:

Die Zertifikate werden nun für mosquitto kopiert. Im Prinzip könnten sie auch aus dem .config-Ordner heraus verwendet werden, aber so hat man alles zusammen. Geschmackssache:

Konfiguration

Es sind zwei offene Ports in der Firewall nötig, die bekommt man durch doppeltes Aufrufen von

Die dabei ausgegebenen Ports merken und gleich benutzen, denn jetzt geht es an’s Einstellen in der vorhin angelegten Konfigurations-Datei. Eine Hilfe dabei war ein Artikel:

Hier im Beispiel ist der normale MQTT-Port (Standard 1833/8883) auf 61883 und zusätzlich ein Websockets-Port (Standard 9002) auf 61884 konfiguriert, beide geschützt mit TLS. Aufgelistet sind hier alle Änderungen im Verhältnis zur Standard-Konfiguration. Die müssen in der Datei jeweils an den entsprechenden Stellen vorgenommen werden. Also nicht einfach alles reinkopieren. Außerdem müssen die $HOME-Variablen manuell aufgelöst werden, also stattdessen direkt/home/username hinschreiben.

Starten und Testen

Es kann fast losgehen, dazu müssen wir aber noch das Verzeichnis, in dem die frisch kompilierte Mosquitto-Bibliothek liegt, in den LD_LIBRARY_PATH aufnehmen, damit beim Ausführen des Binarys gleich auch darin nach ihr gesucht wird:

$HOME/lib/ wird an den bisherigen Pfad angehängt und dann wieder in der Umgebungsvariablen gespeichert (der Doppelpunkt ist das Trennzeichen), danach wird sie ausgegeben. Damit das fortan automatisch beim Einloggen geschieht, ergänzen wir die erste Zeile in der .bashrc:

Und jetzt braucht man vier Konsolen-Fenster:

1. Der Broker. Hier sollten zum Start ein paar Meldungen erscheinen:

2. Das Log. Auch hier sollten bei den folgenden Aufrufen einige Meldungen erscheinen:

3. Der Subscribe-Client. Er sollte beim nächsten Aufruf die gesendete Nachricht anzeigen:

4. Der Publish-Client:

Ein  uberspace-list-ports -l  zeigt außerdem die jetzt offenen Ports mit dem horchenden Mosquitto-Server:

Als nächsten Schritt kann man jetzt die OwnTracks-App mit dem Broker verbinden. Das sollte sich ebenfalls in den Logs und im Subscribe-Client niederschlagen, außerdem müsste in Luxembug ein User angezeigt werden.

Die Websocket-Verbindung kann man direkt hier testen: http://www.eclipse.org/paho/clients/js/utility/index.html
Oder einen dieser MQTT-Websocket-Clients klonen und konfigurieren:
https://github.com/eclipse/paho.mqtt.javascript.git
https://github.com/jpmens/simple-mqtt-websocket-example
https://github.com/owntracks/contrib

Daemontools

Zur besseren Kontrolle des Brokers übergibt man ihn in die Obhut der  deamontools (die zum Testen gestartete Instanz in der “1. Konsole” muss natürlich vorher per Strg+C beendet werden):

In dieses Skript kommt nun (den Usernamen ersetzen):

Zum Abschluss wird das Skript ausführbar gemacht, aktiviert und der Daemon gestartet:

Ein abschließendes

sollte nun den Mosquitto-Superviser und den eigentlichen Broker zeigen.

Das war’s, alles geht! 🙂

Achtung, mit dieser Konfiguration gestattet der Broker alle Verbindungen und Subscriptions! Eine ACL würde Abhilfe schaffen…

Bliebe noch,  den ot-recorder und ein Authentifikations-Backend einzurichten. Mal schauen, wann das kommt…

Update: ot-recorder

Der ot-recorder klappt auch, wegen der Nachfrage in den Kommentaren hier noch ein kleiner Hinweis dazu. Ist leider aus Zeitmangel nicht ganz so ausführlich, aber besser wie nix:

Ich habe Version 0.6.5 vom 30. Mai 2016 ans Laufen bekommen und beziehe mich daher hier auf diese, würde mich aber nicht wundern, wenn auch eine neuere Version funktionieren würde. Vielleicht einfach mal ausprobieren. Leider weiß ich nicht mehr genau den Weg, den ich damals genommen habe, und kann daher nur Hinweise geben, keine Anleitung.

Man benötigt wohl auch noch die libconfig in Version 1.5 (möglicherweise geht auch hier die neuere 1.6?). Die kann man einfach runterladen, in ein Verzeichnis entpacken (in meinem Fall /home/$USERNAME/projekte/libconfig/libconfig-1.5), dann

ausführen und hernach

Das reicht schon, dann ist die Bibliothek dort verfügbar.

Es sieht so aus, als wären die nötigen Änderungen im Ordner von owntracks-recorder allesamt in der config.mk und dessen Kompilieren sollte danach klappen. Würde mich freuen von jemandem, der es ausprobiert hat, eine Rückmeldung zu bekommen. Also, meine config.mk hat folgende Änderungen:

($USERNAME jeweils von Hand ersetzen durch den eigenen Benutzernamen, die anderen Pfade jeweils auf eigene Gegebenheiten anpassen)

Nach dem Kompilieren müsste ./owntracks-recorder funktionieren. Allerdings gab es, wenn ich mich recht erinnere, noch kleinere Probleme, die Web-Oberfläche aufzurufen, die ich nie wirklich behoben habe, weil mir die Daten in den Verzeichnissen schon gereicht haben.

Ich hoffe, das hilft schonmal?