Technische Dokumentation - Glopsch/dashboard GitHub Wiki
Installation
Der Installationsprozess startet mit dem Herunterladen des vorgefertigten Custom-Image aus dem GitHub Repository. Das Image beinhaltet bereits alle benötigten Softwareelemente und muss nur noch auf eine passende Micro-SD geflasht werden.
Ist das Image erfolgreich aufgespielt worden, kann der Anwender den Raspberry mit Strom versorgen und via Ethernet-Kabel mit seinem Router oder Switch verbinden. Der Raspberry bekommt über DHCP eine IP Adresse zugewiesen und startet die entsprechenden Dienste für das Web Dashboard über ein Startskript beim Bootvorgang. Da in der “hosts” Datei der Localhost-Eintrag auf den DNS Namen http://dashboard zeigt, ist das System unabhängig vom eingesetzten IP-Adressbereich.
Dem Endanwender ist es nun möglich, über einen Browser das Web Dashboard in seinem lokalen Netzwerk aufzurufen. Auf der Login Seite kann der Anwender ein neues Kennwort vergeben und sich anmelden.
Webserver
Aufbau
Zur schnellen und effizienten Bereitstellung der Webanwendung fiel die Entscheidung auf ein Node.js-Backend mit eingebundenem Express-Modul. Diese Kombination ist für das Projekt deshalb ideal, weil es einerseits mit Javascript als Programmiersprache eine einheitliche Programmierung in Front- und Backend ermöglicht, andererseits bietet Express die Möglichkeit, mit sehr geringem Aufwand, nicht nur statische Dateien bereitzustellen, sondern liefert bereits ein grundsolides Framework für die Realisierung einer RESTful-API, über welche die Authentifizierungs- und Scan-Dienste sicher bereitgestellt werden können.
Des Weiteren bietet diese Laufzeitumgebung eine Vielzahl von vorgefertigten Paketen, die im Kontext des Projekts konstruktiv sein könnten. Zum Einsatz kamen unter anderem die Pakete für node-nmap, ip und dotenv, welche über den integrierten Paketmanager schnell zur Verfügung standen. Das Framework Express.js erweitert die Laufzeitumgebung um die serverseitige Webkomponente und erleichtert das Erstellen der eigentlichen Webanwendung.
HTML-, CSS- und Javascript-Dateien werden statisch als public data übermittelt, da sie an sich keine Sicherheitsrelevanz haben. Daher sind keine vorherigen Prüfungen nötig und die einzelnen Seiten können schnell geladen werden.
Für die visuelle Darstellung des Dashboards wird neben eigenentwickelten Design-Bausteinen zusätzlich das weitverbreitete CSS-Framework Bootstrap verwendet, um eine zeitgemäße und intuitive User Experience zu schaffen, indem das Framework einerseits zur Erleichterung bei der Realisierung von Responsivität und Strukturierung sowie leicht wiedererkennbaren Steuerelementen beiträgt und andererseits eine Reduzierung des Zeitaufwands bei der Umsetzung des Benutzeroberflächen-Designs ermöglicht.
Scan-Funktionalitäten und Benutzerauthentifizierung wurden als RESTful-API-Schnittstellen realisiert. So wird ein einheitlicher und sicherer Zugriff ermöglicht, auch im Falle von möglichen Weiterentwicklungen, bei denen die Dienste nicht über das aktuelle Dashboard angefragt würden.
Benutzerauthentifizierung
Zur Gewährleistung der Sicherheit des Systems ist die Nutzung ausschließlich bei vorheriger Anmeldung möglich. Hierfür bietet der Webserver jeweils eine Schnittstelle zur Initialisierung und zur Anmeldung des Nutzers, sowie Funktionalitäten für ein Token-basiertes Session-Management für erhöhte Benutzerfreundlichkeit.
Bei der Initialisierung wird das Initial-Passwort überprüft und das neue Benutzerpasswort durch bcryptjs, welches durch hervorragende Sicherheitsmaßnahmen besticht, verschlüsselt, bzw. gehasht und das Ergebnis in einer Binärdatei auf dem Server abgelegt. Von diesem Punkt an ist das System nicht mehr mit dem Initial-Passwort zugänglich. Wird das gesetzte Passwort vergessen, muss das System erneut aufgesetzt werden. Dieser vermeintliche Umstand dient allerdings ebenfalls der erhöhten Sicherheit vor unbefugten Zugriffen.
Meldet sich der Nutzer nach der Initialisierung mit seinem Passwort an bzw. ist der Vergleich von dessen Hashwert mit dem gespeicherten Hashwert im Server erfolgreich, generiert das System einen JWT (JSON Web Token), der an den Nutzer übermittelt, in dessen Browser gespeichert und von da an bis zum Zeitpunkt des Ablaufs oder der Abmeldung zur Authentifizierung genutzt wird.
Für die Abfrage von sicherheitsrelevanten Funktionen, sprich dem Netzwerkscan und den Detailscans, wird der zuvor empfangene Token bei jeder Anfrage aus dem Lokalspeicher des Browsers ausgelesen und mit dem jeweiligen fetch-Aufruf im Request-Header mitgereicht. Ist die serverseitige Prüfung des Tokens erfolgreich, wird die entsprechende Anfrage ausgeführt, andernfalls wird eine Fehlermeldung zurückgegeben. Zur Erstellung und Prüfung des Tokens wird das Package jsonwebtoken verwendet, da es einfach und sicher zu implementieren ist und hohe Zuverlässigkeit bietet.
Scanvorgänge
Verwendetes Framework
Um ein Netzwerk auf verbundene Geräte und deren Eigenschaften zu prüfen, wird das Framework Nmap (nmap.org) verwendet. Dieses ist ein Open Source Projekt, das im Bereich der Netzwerkscans ein weitverbreiteter Standard ist. Für das Dashboard enthält es alle benötigten Funktionen zur Netzwerkanalyse enthalten. Darüber hinaus ermöglichen es verschiedene Packages auch, Nmap unter Javascript anzuwenden.
Übersicht unterschiedliche Scan-Typen
Die Netzwerkanalyse wird angestoßen, nachdem sich der Anwender angemeldet hat und auf die Startseite navigiert ist. Ist die Authentifizierung am Server erfolgreich, wird der erstmalige Netzwerkscan ausgelöst. Bei dessen Erfolg werden die gewonnenen Daten wie DNS-Namen, IP-Adresse, MAC-Adresse und Gerätehersteller (Vendor) an das Frontend zurückgegeben und im Dashboard dargestellt. Solange sich der User auf der Startseite befindet, wiederholt sich der Scan zyklisch und aktualisiert die gefundenen Geräte. Für einzelne Geräte kann der Endanwender detaillierte Scans starten, welche das Betriebssystem, offene Ports und deren Services liefern.
Grundfunktionalität
Die Grundfunktionalität ist bei Netzwerkscan und Detailscan ähnlich: Ausgelöst durch ein bestimmtes Client-seitiges Event wird mittels fetch-Aufruf eine Anfrage an die für die Art des Scans zuständige API-Schnittstelle übermittelt. Sobald diese die Anfrage entgegengenommen hat, wird, wie im Abschnitt „Benutzerauthentifizierung” bereits beschrieben, der Header der Anfrage auf ein gültiges Token überprüft. War dies erfolgreich, wird die Anfrage an die eigentliche Handler-Funktion weitergereicht. Die Handler-Funktion liest nun jeweils die Anfrage-Parameter aus und übergibt jene an den vom Modul node-nmap gestellten Handler. Hierbei ist noch anzumerken, dass im Falle des Netzwerkscans zunächst die Netzwerkadresse ermittelt werden muss. Dafür wird auf Betriebssystemebene der Befehl
ip -o -f inet addr show | awk '/scope global/ {print $4}'
aufgerufen. Zur korrekten Formatierung wird das leichtgewichtige Package ip verwendet. Wird nun mit der gewonnenen Netzwerkadresse als Parameter der entsprechende Nmap-Befehl aufgerufen, erhalten wir als Rückgabewert ein JSON-Objekt, welches Basisdaten zu sämtlichen im Netzwerk befindlichen Geräten enthält.
Im nächsten Schritt wird der eigentliche Scan ausgeführt. Hierfür werden, wie weiter unten genauer beschrieben, je nach Typ des Scans die entsprechenden Parameter für die Nmap-Anwendung an node-nmap übergeben, welches die Kommunikation mit besagter Anwendung regelt. Nmap an sich sendet gezielte Anfragen über das Netzwerk, sammelt und verarbeitet Informationen zu gefundenen Geräten und liefert die Ergebnisse zurück an node-nmap, welches sie im letzten Schritt wohlgeformt als JSON-Objekt zurückgibt. Abhängig davon, ob der Scanvorgang erfolgreich war, sendet der Server als Antwort entweder die gewonnenen JSON-Daten oder schickt den Status-Code 500 (internal server error).
Netzwerkscan
Während sich Backend-seitig die Unterschiede zwischen Netzwerk- und Detailscan im wesentlichen auf den verwendeten Nmap-Befehl beschränken, sind auf Frontend-Seite die größeren Unterschiede erkennbar: Der Netzwerkscan kann auf zweierlei Arten angestoßen werden: Beim Laden der Startseite und zyklisch. Für den ersteren Fall wird der entsprechende Funktionsaufruf direkt beim Aufbau der Seite gestartet. Somit kann eine Aktualisierung der Netzwerkanzeige durch einen einfachen Reload erreicht werden. Für den zyklischen Aufruf wird nach erfolgreichem ersten Scan ein Timer gestartet, welcher in gleichmäßigen Zeitabständen ein Event auslöst, welches wiederum den fetch-Aufruf für den Netzwerkscan auslöst. Im Backend wird daraufhin nach oben beschriebenen Schema unter Übergabe der Netzadresse der Befehl
-sn -R -T5
an Nmap übergeben. Dieser erkennt sämtliche verbundene Geräte sowie deren DNS-Name, IP- und MAC-Adresse und den Hersteller (Vendor).
Bei erfolgreicher Rückmeldung werden die gewonnenen Daten ausgelesen, strukturiert und die entsprechenden Anzeigeelemente im DOM erstellt. Zur Identifizierung der gefundenen Geräte werden die Elemente mit spezifischen IDs versehen. Über diese können später gezielte Detailscans angefragt und die resultierenden Daten den korrekten HTML-Elementen zugeordnet werden.
Detailscan
Die Detailscans werden ausschließlich manuell durch Klicken auf den entsprechenden Button gestartet. Die Anfrage dafür unterscheidet sich dahingehend von der zum Netzwerkscan, als dass die entsprechende IP-Adresse des anzufragenden Gerätes mitgeliefert wird. Diese wird zuvor durch die ID des dafür ausgezeichneten HTML-Elements ermittelt und an den fetch-Aufruf mit angehängt. Die Übernahme vom Backend erfolgt dann aus der API-Anfrage heraus.
Nach erfolgreicher Authentifizierung und Weiterleitung an die Handler-Funktion wird, analog zum Netzwerkscan, aus dem node.js-Server heraus ein entsprechender Nmap-Befehl aufgerufen. Für den Detailscan, bzw. den Scan des Betriebssystems und offener Ports, entschieden wir uns hierbei für den entsprechenden vom node-nmap-Modul mitgelieferten Befehl. Dieser hatte sich nach sorgfältiger Prüfung von Alternativen als am schnellsten und für die Produktivumgebung am kompatibelsten erwiesen.
Wurde der Befehl erfolgreich ausgeführt, wird das Ergebnis, wieder analog zum Netzwerkscan, als JSON Datei an das Frontend übermittelt und strukturiert. Über die Geräte-IDs werden nun die neu zu erzeugenden HTML-Elemente mit den bereits bestehenden Anzeigeelementen des betroffenen Gerätes in Verbindung gebracht und dort eingefügt. Dieser Vorgang erfolgt mit identischem Ablauf für sämtliche vom Netzwerkscan gefundene Geräte. Mit Klick auf den entsprechenden Button können die Ergebnisse des Detailscans wieder ausgeblendet werden. Aktualisiert werden können die Ergebnisse, in dem man erneut auf den Button klickt.