MQTT-Broker einrichten/ Broker TLS
Beschreibung
BearbeitenDer Broker wird so eingerichtet, dass TLS-verschlüsselte Verbindungen verwendet werden. Ergänzend zu dem Beispiel im Abschnitt MQTT-Broker einrichten/ Multiple Listener wird hier auch die Generierung der Zertifikate beschrieben.
Bei Nutzung von TLS wird zunächst zwischen beiden Punkten eine Verschlüsselung ausgehandelt. Ist eine verschlüsselte Verbindung etabliert, wird im nächsten Schritt die eigentliche Anmeldung am Broker vorgenommen, mit der eventuell notwendigen Übertragung von Zugangsdaten. Ohne TLS-Verschlüsselung würden die Zugangsdaten unverschlüsselt über das Netzwerk gehen. Dies ist nur in wenigen Situationen vertretbar. Somit ist es ein Muss, TLS einzusetzen, sobald eine Authentifizierung notwendig ist. Umgekehrt gilt: Für Fälle, in denen kein TLS verwendet werden kann, bringt eine Nutzerverwaltung mit Zugangsdaten keine Sicherheit.
Zertifikate erzeugen
BearbeitenDie Erzeugung der Zertifikate wird unter einer Unix-Shell mit OpenSSL beschrieben. Diese Software ist für die häufigsten Plattformen verfügbar. Für andere Programme unterscheiden sich die Details, aber der Ablauf ist gleich. Folgende Anleitung baut auf Beschreibung unter http://www.steves-internet-guide.com/mosquitto-tls/ auf. [1]
Root-Schlüssel erstellen
BearbeitenEin Root-Zertifikat wird benötigt, um andere Zertifikate zu unterschreiben. Das eigentliche Zertifikat besteht aus geheimen und öffentlichen Schlüssel. Der öffentliche Schlüssel wird später verwendet, um die Signaturen durch den privaten Schlüssel prüfen zu können.
Das eigentliche Zertifikat wird erzeugt mit:
openssl genrsa -aes256 -out <Dateiname-root>.key <Schlüssellänge>
Der Dateiname sollte sprechend sein. Die Schlüssellänge sollte mindestens 2048 Bit lang sein, besser 4096 Bit. Die Länge wirkt sich deutlich auf die Erstellungszeit des Schlüssels aus, auch wenn es sich hier im Bereich von Sekunden handelt und somit in den meisten Fällen vernachlässigbar ist. Weitere Aktionen sind ebenfalls von der Schlüssellänge beeinflusst. Da dieser Schlüssel aber nur zur Zertifizierung anderer Schlüssel dient und nicht für die Verschlüsselung der Kommunikation, wirkt sich dies nur geringfügig aus. Die Schlüssellänge kann so groß wie möglich gewählt werden, auch wenn Experten den Sicherheitsgewinn einer Schlüssellänge > 8192 als zu gering werten.
Mit dem Parameter -aes256 wird der Schlüssel mit AES256 verschlüsselt. Alternativ können andere Verschlüsselungsroutinen und Schlüssellängen, wie Camellia (mit -camellia128, -camellia192 oder -camellia256), DES (mit -des3) oder IDEA (mit -idea). Die aktuell unterstützte Liste wird mit man openssl genrsa angezeigt.
Das Passwort mit dem der Schlüssel gesichert wird, wird bei jeder Nutzung des Schlüssels abgefragt.
Root-Zertifikat selbst signieren
BearbeitenFür das Signieren der MQTT-Zertifikate muss das Root-Zertifikat ebenfalls signiert sein. Steht keine Public-Key-Infrastructure zur Verfügung, mit dem Zertifikate signiert werden können, bieten sich selbst signierte Zertifikate an. Dann muss an jedem Gerät, welches Zertifikate nutzt, das von diesem Root-Schlüssel signiert wurde, das entsprechende Root-Zertifikat eingerichtet werden. Für kleinere Installationen ist dies mit vertretbarem Aufwand verbunden. Ist es absehbar, dass die Installationen größer werden, sollte eine Public Key Infrastruktur aufgebaut werden. Hier aber die Schritte, um aus dem oben generierten Schlüssel ein selbst-signiertes Zertifikat zu erstellen.
Zunächst wird aus obigem Schlüssel eine Zertifikatsanforderung erstellt:
openssl req -new -x509 -days 1826 -key <Dateiname-root>.key -out <Dateiname-root>.crt
Anschließend wird das Zertifikat mit Inhalt gefüllt. Wenn in der zugehörigen Konfigurationsdatei keine passenden Standardwerte enthalten sind, müssen diese per Hand eingetragen werden. Abgefragt werden Angaben zum Ort, zu dem Namen und E-Mail-Adresse des Verantwortlichen.
Die erzeugte Datei mit der Endung .crt beinhaltet das selbst-signierte Zertifikat, welches im weiteren Verlauf für die Signierung der Broker-Zertifikate verwendet wird.
Broker-Zertifikat erzeugen
BearbeitenPrinzipiell wird das Zertifikat auf dem Rechner erstellt, wo dieses Zertifikat genutzt wird. Zu dem Zertifikat gehört ein privater Schlüssel, welcher auf möglichst wenigen Rechnern bzw. Festspeichern auftauchen soll.
Das Broker-Zertifikat wird analog zum Root-Zertifikat erzeugt:
openssl genrsa -out <Dateiname>.key <Schlüssellänge>
Es fehlt der Parameter -aes256: Dieser Parameter würde den privaten Schlüssel mit AES256 und einem einzugebenden Passwort noch einmal verschlüsseln. Bei Einsatz auf dem Broker muss bei Start des Brokers dieses Passwort übergeben werden. Dieser Neustart geschieht in der Regel über Hintergrunddienste, wo kein Passwort über Tastatureingaben übergeben werden kann. Die Aktivierung endet mit einer Fehlermeldung. Wird das Passwort in einer Konfigurationsdatei gespeichert, um bei Aufruf das Zertifikat zu entsperren, liegen Zertifikat und (Klartext-)Passwort in einer von diesem Gerät erreichbaren Stelle zugänglich. Der Sicherheitsgewinn ist daher marginal.
In den meisten Fällen macht dies für ein Broker-Zertifikat keinen Sinn.
Während bei einem Root-Zertifikat die Schlüssellänge größer gewählt werden kann, reicht bei einem Client-Zertifikat eine kleinere Schlüssellänge aus. Kleiner als 2048 sollte nur genutzt werden, wenn Speicherplatz bzw. Rechenleistung wichtiger einzustufen sind. Dieser Schlüssel wird verwendet, um die Kommunikation zu verschlüsseln. Die Schlüssellänge kann einen deutlichen Einfluss auf die benötigte Rechenleistung bzw. Übertragungslatenz haben. Dieser Einfluss mag gering erscheinen, aber in mittelgroßen Installationen sich bereits deutlich auswirken.
Broker-Zertifikat signieren
BearbeitenAus oben hergestelltem (privatem und öffentlichem) Schlüssel wird zunächst eine Signaturanforderung (englisch: certificate signing request) erstellt:
openssl req -new -key <Dateiname>.key -out <Dateiname>.csr
Es werden für das Zertifikat einige Daten abgefragt. Bei kleineren Installationen sind diese Werte nicht in einer Konfiguration vordefiniert, so dass hier manuell sinnvolle Werte eingetragen werden müssen. Als Common Name (CN) wird der Name eingetragen, unter dem der Broker erreichbar ist. Anhand dieses Wertes prüft der Client, ob das Zertifikat zu dem Namen passt. Wird der Broker über die URL mqtt.local angesprochen, wird dies als Common Name eingetragen. Soll der Broker über die IP-Adresse angesprochen werden, ist dies als Common Name zu verwenden.
Tipp: |
Unter anderem wird ein Common Name, CN abgefragt. Dieser Wert wird der Broker als Nutzernamen verwenden, mit dem zusätzlich eine Nutzerverwaltung eingerichtet werden kann. |
---|
Diese erstellte .csr Datei wird auf den Rechner mit dem Root-Zertifikat (siehe oben) übertragen. Diese Datei enthält keinen privaten Schlüssel. Auf dem Signaturrechner wird diese Signaturanforderung mit dem Zertifikat signiert:
openssl x509 -sha256 -req -in <Dateiname>.csr -out <Dateiname>.crt -CA <Dateiname-root>.crt -CAkey <Dateiname-root>.key -CAcreateserial -days <Tage>
Benötigt werden die Dateien des Server-Zertifikates. Diese Signaturen sollten eine begrenzte Haltbarkeit haben, welche mit <Tage> eingestellt wird.
Die erzeugte Datei <Dateiname>.crt wird zusammen mit dem Root-Zertifikat <Dateiname-root>.crt auf den Broker kopiert.
Konfiguration
BearbeitenEs wird ein neuer Listener auf Port 8883 eingerichtet:
listener 8883
tls_version tlsv1.2
psk_file /etc/mosquitto/pskfile.txt
cafile /etc/mosquitto/ca_certificates/ca.crt
keyfile /etc/mosquitto/certs/mqtt.key
certfile /etc/mosquitto/certs/mqtt.crt
Die einzelnen Zeilen bedeuten:
- listener 8883
- Es wird ein neuer Port 8883 auf allen verfügbaren Netzwerkschnittstellen angebunden.
- tls_version
- (mosquitto >= v2.0) Es wird die minimale TLS-Version angegeben, die akzeptiert wird. (mosquitto < v2.0) Es muss die komplette Liste der akzeptierten TLS-Versionen eingetragen werden.
- psk_file
- Pfad zur Datei mit den Pre-Shared-Keys
- cafile
- Pfad zu Zertifikat der CA.
- keyfile
- Pfad zum privaten Schlüssel, mit dem der MQTT-Broker die Verschlüsselung durchführt.
- certfile
- Pfad zum Zertifikat des privaten Schlüssels, unterzeichnet von der CA, dessen selbst-signiertes Zertifikat oben angegeben ist.
Klient-Konfiguration
BearbeitenOben wurde für den Broker ein Zertifikat auf den Namen mqtt.local erstellt und von einer separaten CA signiert. Der Klient benötigt das selbst-signierte Zertifikat der CA <Dateiname-root>.crt, um das Broker-Zertifikat zu prüfen.
Ohne das selbs-signierte Zertifikat muss der Klient eine unsichere Verbindung akzeptieren. Ebenso muss der Klient eine unsichere Verbindung akzeptieren, wenn der Broker über eine andere Adresse angesprochen wird als über mqtt.local.
Folgende Beispiele zeigen verschiedene Möglichkeiten mit dem entsprechenden Konsolen-Programm:
mosquitto_sub -h mqtt.local -p 8883 -t '#' --cafile <Dateiname-root>.crt
mosquitto_sub -h mqtt.local -p 8883 -t '#' --insecure # verzichtet auf Prüfung des Broker-Zertifikates
mosquitto_sub -h 192.168.1.3 -p 8883 -t '#' --insecure # Hostname passt nicht zum Common Name des Zertifikats, was zu einem Fehler führen würde
Härten
BearbeitenDie TLS-Kommunikation erhöht bereits die Sicherheit der Kommunikation. Das TLS-Protokoll wird basierend auf der allgemeinen Sicherheitssituation weiterentwickelt, so dass immer wieder neue Versionen veröffentlich werden, die zu dem Zeitpunkt als sicher gelten. Ebenso werden Versionen als unsicher markiert, wenn gravierende Sicherheitslücken bekannt werden. Zu einer Version der TLS-Kommunikation gehören aber dennoch verschiedene Teilpunkte, so müssen beide Partner sowohl die Verschlüsselungsroutine (cipher) und Hash-Routine aushandeln. Hier kann es sein, dass mit der Zeit einzelne Routine unsicher werden und nicht mehr verwendet werden sollten.
TLS-Version
BearbeitenEs sollte eine Minimum-Version von TLS angegeben werden, die so hoch wie möglich ist. Die Entwicklung wird von der IETF betrieben und die aktuell gültige Version wird von dieser Organisation bekannt gegeben. Ebenso wird dort eine Liste gepflegt, welche Versionen noch unterstützt werden und welche nicht mehr verwendet werden sollte.
Die Version wird mit dem Schlüsselwort tls_version definiert. Bei mosqitto-Version älter 2.0 wird die komplette Liste an zu unterstützenden Versionen angegeben. Diese Liste wird mit Leerzeichen getrennt. Ab mosquitto Version 2 wird hiermit die minimale Version angegeben. Die aktuell gültige Version 1.3 besitzt zusätzliche Sicherheitsmerkmale, die ältere Versionen nicht unterstützen, so dass TLS nur ab Version 1.3 eingesetzt werden sollte.
mosquitto < 2.0
BearbeitenMit folgendem Schlüsselwort wird für einen Listener die TLS-Versionen festgelegt:
tls_version tlsv1.1 tlsv1.3
Der Broker akzeptiert Anfragen mit TLS 1.1 und TLS 1.3, aber nicht Anfragen mit TLS 1.2. Aus Sicherheitsgründen sollte TLSv1.1 nicht mehr verwendet werden und TLSv1.2 nur, wenn es noch notwendig ist.
mosquitto >= 2.0
BearbeitenMit folgendem Schlüsselwort wird für einen Listener die TLS-Versionen festgelegt:
tls_version tlsv1.2
Der Broker akzeptiert alle Verbindungen mit TLSv1.2 und höher. Aus Sicherheitsgründen sollten Verbindungen nur noch ab TLSv1.3 eingesetzt werden.
Verschlüsselungsroutinen
BearbeitenUnabhängig von der TLS-Version kann es passieren, dass systematische Schwächen einzelner Routinen bekannt werden, so dass man diese aus der Nutzung ausschließen möchte. Ein anderer Grund kann in der Performance liegen. Viele Verschlüsselungsroutinen lassen sich in verschiedenen Betriebsmodi verwenden, welche nicht nur Auswirkung auf die Sicherheit, aber auch auf die Ausführungsgeschwindigkeit haben. Je nach einzubindenden Geräte ist es sinnvoll, die Verschlüsselungsroutinen so zu wählen, dass die Prozesserlast der verwendeten Geräte nicht übermäßig belastet werden.
Ab Version TLSv1.3 gab es Änderungen bei den verwendeten Verschlüsselungsroutinen, was durch Verwendung eigener Kommandos in der Konfiguration abgebildet wird. Die Verschlüsselungsroutinen werden mit den Schlüsselwörtern ciphers für TLSv1.2 und älter bzw. cipher_tls1.3 für TLSv1.3:
ciphers ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES256-GCM-SHA384
ciphers_tls1.3 TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_GCM_SHA256
Die einzelnen Zeilen bedeuten:
- ciphers
- In dieser Zeile werden einzelne Verschlüsselungsroutinen mit elliptischen Kurven verwendet
- ciphers_tls1.3
- Dies ist die Standard-Einstellung bei Verwendung von TLSv1.3
Eigener Listener
BearbeitenSind im Netzwerk noch Geräte vorhanden, welche die aktuellen TLS-Versionen nicht unterstützen, bietet sich an, diese über einen eigenen Listener oder Broker anzubinden. Für diesen Listener wird dann über die Firewall der Zugriff auf die entsprechenden Geräte begrenzt.
Listener 48883 192.168.3.1
tls_version tlsv1.0 tlsv1.1
ciphers ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES256-GCM-SHA384
...
Dieser Listener lauscht auf Port 48883 der IP-Adresse 192.168.3.1. Für diese Kombination können eigene Firewall-Regeln angelegt werden, so dass nur die Geräte mit diesem Listener Verbindung aufnehmen können, die aktuelle TLS-Versionen nicht unterstützen. In diesem Fall muss aber eine Durschsicht der Verschlüsselungsroutinen erfolgen und schwache Routinen ausgeschlossen werden. Dies erfolgt mit dem Schlüsselbegriff ciphers.
Ausblick
BearbeitenAuf dem Broker ist ein Listener eingerichtet, welcher TLS-verschlüsselte Verbindungen anbietet. Erst mit einer verschlüsselten Verbindung macht einer Nutzerverwaltung auf dem Broker Sinn, da Nutzer und Passwort nicht mehr unverschlüsselt über das Netzwerk laufen.
Es lassen sich auf dem Broker verschiedene Listener einrichten, die unterschiedliche Geräte anbinden. Wird der Broker auf einem Router platziert, der verschiedene Netzwerke bedient, lassen sich z.B. Geräte der Heimautomation in einem internen Netzwerk platzieren, die anonym über eine unverschlüsselte Verbindung mit dem Broker kommunizieren. Dieses Netzwerk muss anderweitig gesichert werden, um Mißbrauch der Heimautomation zu verhinden. Über einen zweiten Listener kann eine verschlüsselte Verbindung angeboten werden, mit der aus einem öffentlichen Netz Telemetriedaten und Befehle in das unverschlüsselte Heimautomationsnetz übertragen werden können.