Unser aktuelles Schlosssystem funktioniert, ist aber schon etwas in die Jahre gekommen. Es basiert auf Bluetooth Pairings. Beim Pairen von zwei Bluetooth Geräten wird ein kryptografischer Schlüssel ausgetauscht. Diesen verwenden wir zur Authentifizierung beim Schlosssystem.
Das System funktioniert gut, ist aber Prinzipbedingt recht langsam. Die gespeicherten Bluetooth Pairings werden der Reihe nach durchprobiert, wobei jedes ein paar Sekunden dauert. Der letzte in der Liste wartet ggf. ein paar Minuten bis sich das Schloss öffnet.
Nebst schnellerer Reaktion soll das neue System auch weitere Vorteile bieten. Welche das aber sind und wie wir das umsetzen, gilt es hier auszuarbeiten.
/dev/watchdog auf RasPi für mehr Zuverlässigkeit. 😉Nach meiner Vorstellung handelt es sich dabei um Software. Die Software wird spezifisch auf die Gegebenheiten eines ganz bestimmten physikalischen Schlosses angepasst. Schloss-Aktuatoren sollen austauschbar sein. Das heisst, die interne Architektur sieht eine einheitliche Schnittstelle vor, über welche die Schloss-Aktuatoren mit dem Authentifizierungsmodul kommunizieren.
Der Schloss-Aktuator signalisiert dem Authentifizierungsmodul, wann es Authentifizierungen entgegennehmen darf und wann nicht. Damit können wir das aktuelle Verhalten abbilden, mit dem nur bei Aussenlicht die Authentifizierung zulässig ist.
Der Schloss-Aktuator kontrolliert natürlich auch das Schloss selber. Dafür erhält er vom Authentifizierungsmodul eine Mitteilung, wenn eine erfolgreiche Authentifizierung stattgefunden hat. In der Ruum42- Situation kann nach erfolgter Authentifizierung das Schloss geöffnet werden, und so lange offen gehalten werden, bis das Licht wieder gelöscht wird. In einer anderen Situation könnte beispielsweise nach „open“-Authentifizierung das Schloss geöffnet und nach „close“-Authentifizierung das Schloss geschlossen werden.
Grafik erstellt mit drawio.
Ein Admin soll Benutzer ohne SSH oder sonstigen Kommandozeilen-Tools verwalten können. Ziel ist Benutzer, Schlüssel und Passwörter einfach verwalten zu können.
# CA Schlüssel und Zertifikat erstellen openssl req -new -x509 -days 14 -extensions v3_ca -keyout ca.key -out ca.crt # Es wird nach einem Passwort gefragt. Hier eines definieren. Es wird später zum Signieren gebraucht. # Der private Schlüssel 'ca.key' muss geheim bleiben und sollte möglichst nicht auf dem Server/Schlosssystem gelagert werden. # Server Schlüssel erstellen openssl genrsa -out server.key 4096 # Signierungsanfrage für den Server-Schlüssel erstellen openssl req -out server.csr -key server.key -new # Den Schlüssel mit dem CA Zertifikat signieren openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out server.crt -days 7 # Informationen zum Zertifikat anzeiten openssl x509 -noout -text -in server.crt # Den RasPi Timestamp anpassen für den Fall, dass es ohne Verbindung zum NTP Server startet sudo touch /var/lib/systemd/timesync/clock
Dies sind ein paar Kommandos, die auf einem Client verwendet werden können, um MQTT zu testen. Sie gehen von einer Verschlüsselten Verbindung über TLS aus. Details zur Konfiguration siehe nächster Abschnitt.
Um diese Kommandos verwenden zu können, muss folgendes installiert werden: sudo apt install mosquitto-clients
# wene-raspi-lock ist der hostname des MQTT brokers in diesem Setup # Alle MQTT Nachrichten abonnieren: (zum Debuggen) mosquitto_sub -h wene-raspi-lock -t "#" -v -p 8883 --cafile path/to/ca.crt # Kommando zum Öffnen an's Schloss schicken: mosquitto_pub -h wene-raspi-lock -t "main-door/lock" -m "open" -p 8883 --cafile path/to/ca.crt # Das Schloss schickt den Status "opened" zurück: mosquitto_pub -h wene-raspi-lock -t "main-door/status" -r -m "opened" -p 8883 --cafile ca.crt # Das Flag '-r' steht für "retain" und bedeutet, dass dieser Wert auf dem Broker als Status gespeichert bleibt und neuen Clients bei Verbindung zugestellt wird.
So wird auf dem RasPi den MQTT Server, genannt „Message Broker“ installiert: sudo apt install mosquitto
Die Konfigurationsdatei /etc/mosquitto/mosquitto.conf enthält ein paar Standardeinstellungen welche wir auskommentieren. Die Einzige Zeile, die aktiv bleibt ist die letzte, welche die Konfigurationen aus den Dateien im Unterverzeichnis conf.d inkludiert.
In /etc/mosquitto/conf.d legen wir folgende Dateien mit entsprechendem Inhalt an:
log_dest syslog
listener 8883 allow_anonymous true cafile /etc/mosquitto/ca_certificates/ca.crt certfile /etc/mosquitto/certs/server.crt keyfile /etc/mosquitto/certs/server.key
Die Datei tls.conf enthält Pfade zu Zertifikaten, welche wir natürlich erst an der Stelle ablegen müssen, damit das funktioniert. Wie sie erstellt werden, wird im Kapitel TLS Self Signed Certificates erklärt. Nachdem die Dateien an den entsprechenden Pfaden liegen, sollte Mosquitto als Eigentümer festgelegt werden: sudo chown mosquitto:mosquitto -R /etc/mosquitto/certs und sudo chown mosquitto:mosquitto -R /etc/mosquitto/ca_certificates.
Um aus Python MQTT zu nutzen, bietet sich Paho an: sudo apt install python3-paho-mqtt
Als NTP Server bietet sich Chrony an. Der kann sehr einfach so konfiguriert werden, die wahre NTP Zeit weiter zu leiten solange es eine Verbindung zu NTP Servern gibt. Wenn diese Verbindung nicht existiert, kann eine angenommene Zeit verbreitet werden.
Dies ist die Konfigurationsdatei in /etc/chrony:
# Welcome to the chrony configuration file. See chrony.conf(5) for more # information about usable directives. # Use Debian vendor zone. pool 2.debian.pool.ntp.org iburst # Use time sources from DHCP. sourcedir /run/chrony-dhcp # Use NTP sources found in /etc/chrony/sources.d. sourcedir /etc/chrony/sources.d # This directive specifies the location of the file containing ID/key pairs for # NTP authentication. keyfile /etc/chrony/chrony.keys # This directive specifies the file into which chronyd will store the rate # information. driftfile /var/lib/chrony/chrony.drift # Save NTS keys and cookies. ntsdumpdir /var/lib/chrony # Uncomment the following line to turn logging on. #log tracking measurements statistics # Log files location. logdir /var/log/chrony # Stop bad estimates upsetting machine clock. maxupdateskew 100.0 # This directive enables kernel synchronisation (every 11 minutes) of the # real-time clock. Note that it can't be used along with the 'rtcfile' directive. rtcsync # Step the system clock instead of slewing it if the adjustment is larger than # one second, but only in the first three clock updates. makestep 1 3 # Get TAI-UTC offset and leap seconds from the system tz database. # This directive must be commented out when using time sources serving # leap-smeared time. leapseclist /usr/share/zoneinfo/leap-seconds.list # Include configuration files found in /etc/chrony/conf.d. confdir /etc/chrony/conf.d # allow usage of local time without real time source local # allow changes using `chronyc settime` manual allow all
Beim Starten des RasPi ohne Zugang zum echten NTP Server wird die Änderungszeit der Datei /var/lib/systemd/timesync/clock verwendet. Leider wird dieser Zeitstempel bei Verwendung von chrony nicht automatisch aktualisiert. Das muss spätestens beim Ausstellen neuer Zertifikate manuell mit sudo touch gemacht werden.