Webserver mit Authentifizierung

Aus der Mikrocontroller.net Artikelsammlung, mit Beiträgen verschiedener Autoren (siehe Versionsgeschichte)
Wechseln zu: Navigation, Suche

Projekt: Arduino-Webserver mit Authentifizierung

1. Anliegen

Einen Webserver mit Arduino zu bauen ist heutzutage kein Kunststück mehr. Wer würde aber einen Webserver mit einer Rolle z.B. in der Hausautomation ohne Anmeldung ins Internet stellen? Das könnte ein Risiko sein. Dazu nachfolgend mein Vorschlag (Prototyp) für die Programmierung eines Webservers mit Authentifizierung. Konkret kann bei einem Arduino-Uno (ATmega328) mit seinen 32kByte Programmspeicher und 2kByte RAM wohl keine Wunder erwarten, es läuft auf Kompromisse hinaus. Die nachfolgenden Ausführungen stellen im Wesentlichen eigene Ideen und Erfahrungswerte dar, also wie ich mir einen einigermaßen sicheren Webservers vorstelle.

2. Hardware

Für den vorgestellten Prototyp des Webservers wurde ein Arduino/Genuino-Uno-R3 Board verwendet. Als Netzwerk-Shield wurde eines mit W5100-Chip und SD-Karten-Slot direkt aufgesteckt. Netzwerkkarten auf der Basis des ENC28J60 funktionieren hier leider nicht. Der Grund: Der W5100 ist höher integriert als der ENC28J60. Letzterer benötigt Speicherplatz für den IP-Stack im RAM des Prozessors (siehe diverse Beiträge in mikrocontroller.net), so dass der Speicher für das vorgestellte Programm nicht mehr reicht (getestet, allerdings mit ATmega32). Wer es aber versuchen möchte: Eine Kombination von Arduino Mega2560 und ENC28J60 wäre durchaus denkbar. Ich habe es mit einem ATmega644 und ENC28J60 (UIPEthernet-Bibliothek) in einer Vorversion erfolgreich ausprobiert. (AVR-Net-IO von Po..., an Arduino-Gegebenheiten angepasst).
Zum W5100-Shield mit SD-Card: Auch hier ist nicht alles Gold, was glänzt. Bei den von mir erworbenen (älteren) Exemplaren habe ich festgestellt, dass diese fehlerhaft bestückt waren. Die Abschlusswiderstände für den Leitungsabschluss sind zu hoch dimensioniert. Folge: Fehlende oder mangelhafte Netzwerkverbindung insbesondere bei kurzen Leitungen infolge von Reflexionen durch Fehlanpassung.
Wie erkenne ich das? Unmittelbar neben der RJ-45 Buchse befindet sich ein kleines SMD-Widerstands-Array. Dies trägt die Aufschrift „511“ – das bedeutet 510 Ohm (Achtung! Neuere Exemplare sind richtig mit „510“ - 51 Ohm bestückt). Jeweils 2 Widerstände sind in Reihe geschaltet – also 1020 Ohm. Die Leitungsimpedanz beträgt für jedes Adernpaar aber nur 100 Ohm. Auch im Schaltplan sind übrigens andere Widerstände angegeben (49 Ohm). Abhilfe: (nur für geschickte Bastler - ohne Garantie!) Parallel zu den Anschlüssen 1 und 2 bzw. 3 und 6 (Leiterseite) der Ethernet-Buchse muss je ein zusätzlicher Widerstand von 120 Ohm eingelötet werden. Bitte alles gut mit Schrumpfschlauch versehen. Die „1“ befindet sich auf der Leiterseite, wenn die Netzwerkbuchse nach oben zeigt, etwa 1,2 cm vom oberen und 1 cm vom linken Rand entfernt. Die weiteren Anschlüsse sind versetzt (oben-1-unten-2-oben-3…), aber in Reihenfolge von links nach rechts, angeordnet. Bei mir gibt es nach dieser Änderung jedenfalls keine Probleme mit kurzen Leitungen mehr.
Was braucht man noch? Vier Leuchtdioden mit Vorwiderständen von wenigstens 330 Ohm (1 kOhm geht auch) helfen, die logischen Zustände an den Ausgängen anzuzeigen. Bitte immer auf solide Verbindungen und Isolation Wert legen – keine wackligen Provisorien!

3. Programm

Gearbeitet wurde mit der Arduino-IDE 1.6.12 unter Windows 10.
Alle nachfolgend angegebenen Dateien sind im Archiv unter: Datei:WebserverAuth.zip gespeichert
Insgesamt werden neben dem Arduino-Sketch noch einige Datendateien (auf der SD-Karte) benutzt. Letzteres sind HTML-Dateien für die Darstellung der Seiten (index.htm, main.htm, frdum.htm sowie frame.htm), Javascript (index.js) und auch Konfigurationsdateien (ip.dat und pwd.dat). Eine Änderung z.B. der IP-Adresse (ip.dat) erfordert also keine Neucompilierung. Man sollte alles, was mit vertretbarem Aufwand auslagerbar ist, in Dateien auf die SD-Karte bringen. Das geht leider nicht so ohne weiteres mit Programmteilen (Harvard–Architektur des Prozessors!).
Im Folgenden sollen einige wesentliche Merkmale, die diesen Webserver auszeichnen, erläutert werden:

  • Ein Zugang zur eigentlichen Hauptseite, auf der sich die Anzeigen (hier nicht realisiert – aber leicht zu integrieren) und Steuer-Buttons befinden, ist nur nach vorangegangener Authentifizierung mit Hilfe eines Kennwortes (5-stellige Zahlenfolge) möglich.
  • Das Kennwort wird auf der Index-Seite (index.htm) mit Hilfe einer vorher im Webserver zufällig gebildeten Zahl (4-stellig) verschlüsselt und mit der POST-Methode (also im Body des Requests) übermittelt. Die Zufallszahl wird mit jedem Zugriff auf die Index-Datei und bei fehlerhafte Anmeldung neu gebildet. Die Verschlüsselung erfolgt über Javascript (index.js).
  • Im Webserver wird die Verschlüsselung mit dem gespeicherten Kennwort (pwd.dat) ebenso vollzogen. Stimmt das Ergebnis des übermittelten Kennwortes damit überein, wird der Zugang zur Hauptseite ermöglicht.
  • Das verschlüsselte Kennwort wird anschließend als Session-ID verwendet. (Ähnliches Prinzip, wie in PHP die Verbindung aufrechterhalten wird). Somit sind anschließend mehrfache Zugriffe auf die Hauptseite ohne Neuanmeldung möglich. Damit können auch Änderungen wie z.B. Betätigung der Buttons angezeigt werden. Alle Daten, die übermittelt werden, gehen per POST-Methode an den Webserver. Stimmt die Session-ID nicht mehr, werden die Inhalte nicht verwertet.
  • Eine Möglichkeit, das Kennwort zu „knacken“, besteht eigentlich nur für einen „men in the middle“ bzw. mit Hilfe eines Sniffers wie z.B. „SmartSniff“. Die Freigabe für die Übermittlung des Javascript-Encrypters (Chiffrators) in der index.js besteht aber nur kurzzeitig bei Aufruf der index.htm – eine direkte Abfrage ist also nicht möglich.
  • Ein Schutz vor „brute force attacks“ wurde durch eine dynamisch veränderte Pausenzeit bei fehlerhafter Anmeldung eingebaut.
  • Das Chiffrierverfahren ist primitiv (ähnlich einer Cäsar-Chiffre) mit anschließender Vertauschung der Stellen. Eine „Rückrechnung“ zur Ermittlung des Kennwortes ist für den „men in the middle“ möglich, führt aber wegen der Vertauschung nicht zu einem eindeutigen Ergebnis. Probieren ist angesagt. Sicherlich sind Hash-Verfahren wie md5 oder sha besser geeignet (hierfür gibt es sowohl Arduino- und auch Javascript-Routinen), aber der Speicherplatz ist beim ATmega328 eben beschränkt.
  • Man sollte beim Kompilieren insbesondere auf die Größe des dynamischen Speicher achten. Werte bei nahe 70% (Erfahrungswert) und darüber sind keineswegs gut. Man riskiert dabei Laufzeitfehler und Abstürze. Leider sind bei der Arduino-IDE keine Warnungen vor Kollisionen mit dem Stapelspeicher eingebaut. Empfehlenswert für mehr Sicherheit wäre es dann, ein Arduino-Mega zu verwenden.
  • Die Verwendung von AJAX für den partiellen Austausch von Inhalten der Hauptseite wurde geprüft. Es lief auch recht gut, leider habe ich es für die Browser in Apple-Geräten (iPod, iPad) nicht hinbekommen – deshalb die Verwendung von IFrames. Bei der Verwendung mehrere IFrames hat wiederum der InternetExplorer gestreikt (wegen des besonderen Verfahrens zur Übermittlung der Session-ID per POST-Methode – frdum.htm). Unter Android lief es auch, allerdings habe ich hier nur mit der Fire-TV-Box von Ama... getestet.

Da dies nur ein Vorschlag / Prototyp für den Aufbau eines etwas sichereren Web-Servers ist, werden sicherlich findige Freaks Verbesserungsmöglichkeiten finden. Weshalb auch nicht – schließlich soll dies hier keine perfekte Arbeit sein, sondern auch anregen, andere Ideen zu entwickeln. Dazu – viel Erfolg!

4. Quellen

Einige wichtige Anhaltspunkte hat mir der Beitrag von Steve, www.hackshed.co.uk/lets-build-a-functional-arduino-webserver, gegeben.