Lesezeit ca. 9 Min.
arrow_back

Eigenleistung


Logo von Raspberry Pi Geek
Raspberry Pi Geek - epaper ⋅ Ausgabe 8/2022 vom 02.06.2022

Webserver im Eigenbau

Artikelbild für den Artikel "Eigenleistung" aus der Ausgabe 8/2022 von Raspberry Pi Geek. Dieses epaper sofort kaufen oder online lesen mit der Zeitschriften-Flatrate United Kiosk NEWS.

Bildquelle: Raspberry Pi Geek, Ausgabe 8/2022

README

Schon mit einfachen Mitteln können Sie einen eigenen HTTP-Server programmieren und mit ihm kommunizieren. Dazu kommen auf TCP-Ebene Netcat und simple Skripte zum Einsatz. So dringen Sie tiefer in die Webtechnik vor und lernen, was hinter den Kulissen eines Browsers geschieht.

Einen Webserver selbst zu programmieren, mag erst einmal als ein ebenso schweres wie überflüssiges Unterfangen erscheinen. Tatsächlich gibt es unter Linux zahlreiche frei verfügbare Webserver, von bekannten Allroundern wie Apache oder Nginx bis hin zu leichtgewichtigen Alternativen wie Cherokee oder Lighttpd („Lighty“).

Allerdings erfordert nicht jede Situation einen ausgefeilten Webserver. Will man einfach nur lokal im eigenen Netzwerk ein paar HTML-Seiten teilen oder die Möglichkeit schaffen, Dateien hochzuladen, dann genügen dazu Linux-Bordmittel. Als passendes Rahmenkonstrukt eignet sich ein ...

Weiterlesen
epaper-Einzelheft 9,99€
NEWS Jetzt gratis testen
Bereits gekauft?Anmelden & Lesen
Leseprobe: Abdruck mit freundlicher Genehmigung von Raspberry Pi Geek. Alle Rechte vorbehalten.
Lesen Sie jetzt diesen Artikel und viele weitere spannende Reportagen, Interviews, Hintergrundberichte, Kommentare und mehr aus über 1050 Magazinen und Zeitungen. Mit der Zeitschriften-Flatrate NEWS von United Kiosk können Sie nicht nur in den aktuellen Ausgaben, sondern auch in Sonderheften und im umfassenden Archiv der Titel stöbern und nach Ihren Themen und Interessensgebieten suchen. Neben der großen Auswahl und dem einfachen Zugriff auf das aktuelle Wissen der Welt profitieren Sie unter anderem von diesen fünf Vorteilen:

  • Schwerpunkt auf deutschsprachige Magazine
  • Papier sparen & Umwelt schonen
  • Nur bei uns: Leselisten (wie Playlists)
  • Zertifizierte Sicherheit
  • Freundlicher Service
Erfahren Sie hier mehr über United Kiosk NEWS.

Mehr aus dieser Ausgabe

Titelbild der Ausgabe 8/2022 von Poka Yoke. Zeitschriften als Abo oder epaper bei United Kiosk online kaufen.
Poka Yoke
Titelbild der Ausgabe 8/2022 von Netzwerker. Zeitschriften als Abo oder epaper bei United Kiosk online kaufen.
Netzwerker
Titelbild der Ausgabe 8/2022 von Info-Zentrale. Zeitschriften als Abo oder epaper bei United Kiosk online kaufen.
Info-Zentrale
Titelbild der Ausgabe 8/2022 von Multi-Sensor. Zeitschriften als Abo oder epaper bei United Kiosk online kaufen.
Multi-Sensor
Mehr Lesetipps
Blättern im Magazin
Container-Hafen
Vorheriger Artikel
Container-Hafen
Trautes Heim
Nächster Artikel
Trautes Heim
Mehr Lesetipps

... schlichtes Shell-Skript, das auf jedem System vorhandene Tools aus dem GNU-Fundus steuert. Die Netzwerkkommunikation übernimmt dabei das oft als Schweizer Taschenmesser für TCP/​IP apostrophierte Tool Netcat .

Bei so einem Projekt ist es am besten, an der Wurzel zu beginnen. Da ein Webserver eben ein Server ist, muss er ständig an einem bestimmten Port mithören und bei Anfragen passende Antworten geben. In der Regel lauschen Webserver bei gewöhnlichen Anfragen am Port 80, wobei dieser Port im Allgemeinen nur HTTP-Anfragen ohne Verschlüsselung entgegennimmt. Der Webserver, den wir im Folgenden erstellen, wird auf den Ports 8080 und 8081 mithören und nur unverschlüsselt kommunizieren. Falls Sie eine Firewall nutzen und den Server im lokalen Netzwerk testen wollen, sollten Sie daran denken, diese beiden Ports für den Webserver freizuschalten.

Eigenbau

Ein Webserver braucht einen Root-Ordner, aus dem er die auszugebenden HTML-Dateien lädt. Zudem benötigt er noch ein Verzeichnis, in dem er hochgeladene Dateien ablegen kann. Die entsprechende Konfiguration definieren Sie zunächst über eine Reihe einfacher Variablen zu Beginn des Server-Skripts (Listing 1). Darüber hinaus müssen Sie die Verzeichnisse und auch die FIFO- Datei entweder manuell oder mithilfe des Test-Builtins der Bash erstellen. Wie das gelingt, demonstriert die fertige Lösung server6.sh, die Sie im Download-Bereich zu diesem Artikel finden.

Here-Dokument: Heredocs dienen in vielen Programmiersprachen zur Definition von Textabschnitten. Im Unterschied zur herkömmlichen Ausgabe per echo oder printf bleiben Zeilenumbrüche, Einzüge und einige Sonderzeichen im Text erhalten. Die Bash erlaubt zudem das Verwenden von Variablen innerhalb des Heredocs.

In der letzten Zeile von Listing 1 sehen Sie dann noch, dass auch die eigene IP-Adresse wichtig ist. Als Netzwerkgerät verwendet der RasPi die WLAN-Schnittstelle wlan0 oder das kabelgebundene Interface eth0. Wenn ein Webbrowser eine Datei über ein Webformular abschicken will, braucht er eine Zieladresse. GET-Anfragen sind die einfachere Variante. Wenn ein Browser eine solche Anfrage stellt, dann erwartet er als Antwort einfach nur den Inhalt einer Webseite, die er dann im Browser-Fenster darstellt.

Passende Dateien für das Testen des Webservers lassen sich skriptgesteuert erstellen. Die Funktion aus Listing 2 durchläuft dazu sieben Mal eine For-Schleife. Darin verwendet die Routine ein Here-Dokument (dritte Zeile), um HTML-Code fast 1:1 eingeben zu können. In solchen Heredocs kann man Bezug auf die in der For-Anweisung gesetzte Variable nehmen, die dann einfach nur die laufende Nummer enthält.

Auf diesem Weg erzeugen Sie mit wenigen Zeilen Code so viele HTML-Dateien, wie Sie für Ihre Tests benötigen. Optional integrieren Sie weitere dynamische Inhalte, die Sie per Skript innerhalb des Here-Dokuments erzeugen. Auch die HTML-Datei, die das Upload-Formular enthält, wird auf diesem Weg in einer anderen Funktion erzeugt.

Am besten testen Sie das Erstellen der HTML-Dateien gleich einmal aus. Danach haben Sie den ersten Meilenstein zur Entwicklung eines Webservers geschafft und können an die Entwicklung weiterer Komponenten gehen. Das Skript im Download-Bereich enthält auch noch eine Funktion, die alle im Root-Ordner enthaltenen HTML-Dateien mit CSS- Code im Header ausschmückt.

GET-Anfragen

Stellt ein Webbrowser eine GET-Anfrage, will er einfach nur Daten zurückbekommen. Wie das aussieht, lässt sich stark vereinfacht austesten: Um etwa zu sehen, was ein Browser macht, wenn man sich nicht an das HTTP-Protokoll hält, führen Sie auf der Kommandozeile echo "hallo Firefox" | netcat ‐l 8080 aus. Dann geben Sie in der Adresszeile des Webbrowsers die URL localhost:8080 ein. Daraufhin sehen Sie, dass Firefox wartet, wartet und weiter wartet – es fehlt offenbar etwas.

Nichtsdestotrotz können Sie aber im Terminalfenster prüfen, wie die Anfrage von Firefox im Klartext aussieht, da der Browser sie bereits an Netcat geschickt hat. Er wartet nun darauf, einen Header und auch HTML als Antwort zu erhalten. Netcat liefert jedoch nichts dergleichen. Mit [Strg]+[C] kappen Sie die Verbindung zu Firefox. Im Browser-Fenster sollte dann der Text aus dem Echo-Kommando erscheinen 1 .

Möchten Sie jetzt wissen, wie eine Antwort von einem echten Webserver aussieht, dann werfen Sie einmal einen Blick in die Ausgabe des Befehls wget ‐‐spider ‐S "https://www.zeit.de/index". Das ist ein Spider-Request von Wget, bei dem es nur darum geht, die Antwort eines Servers herauszufiltern. Der informiert in der ersten Zeile mit HTTP/1.1 200 OK, dass er mit einer HTTP-Anforderung zufrieden ist. Mit weiteren Zeilen in Form von Wertepaaren (etwa Connection: keep‐alive, Content‐Length:) sendet er zusätzliche Informationen oder Anweisungen zurück.

Es scheint sich bei diesem Dienst auch um einen gut abgesicherten Webserver zu handeln, denn er gibt nicht preis, um was für ein Server-Programm es sich genau handelt. Viele Server outen sich an dieser Stelle zum Beispiel als Server: nginx – nicht ratsam, weil es Angreifern die Arbeit erleichtert. Rein technisch gesehen wird diese Information auch gar nicht benötigt.

FIFO-Datei

Netcat steht auf nahezu jedem Linux-System zur Verfügung und lässt sich mit etwas Kreativität für viele Zwecke verwenden, wobei es auch seine Grenzen hat. Basisoperationen im Netzwerk lassen sich damit gut emulieren, komplexe Interaktionen dagegen nur schwer oder gar nicht. Den Plan, Apache oder Nginx mit Netcat Konkurrenz machen zu wollen, muss man definitiv aufgeben.

Wenn Sie möchten, dass Netcat dauerhaft an einem Port lauscht und auch verschiedene Antworten versenden kann, müssen Sie es in einer Schleife mit einer FIFO-Datei kombinieren. Das Kürzel FIFO steht für das Prinzip „first in, first out“. Die Informationen kommen also in derselben Reihenfolge wieder aus der Datei, in der sie hineingeschrieben wurden . Listing 3 stellt das exemplarisch dar. Später zeigen wir noch eine Möglichkeit, diese Schleife per Log-Funktion zu optimieren.

Die FIFO-Datei sorgt dabei für eine bessere Kommunikation zwischen Netcat und der Funktion antworten, die Listing 4 zeigt. Netcat lauscht an dem angegebenen Port und schreibt in die FIFO-Datei. Auf der linken Seite der Pipe sehen Sie den Aufruf der Funktion, die die Anfrage des Browsers aus der FIFO-Datei herausliest. Sie wertet sie aus und schickt dann durch die Pipe hindurch eine passende Antwort zu Netcat zurück, die einen HTML-Header und HTML-Daten enthält. Die Funktion antworten entscheidet, was der Server an den Browser zurückgibt.

Diese Variante stellt bereits eine ziemlich leistungsfähige Lösung dar. Beträgt die Länge der Browser-Anfrage 1 (Zeile 3), dann lautet sie /, falls nicht (Zeile 5), dann soll eine Datei aus dem Root-Verzeichnis wiedergegeben werden. Um den Webserver dazu zu veranlassen, dass er die im Root-Ordner enthaltenen Dateien wiedergibt, genügt erst einmal ein ganz schlichtes ls Verzeichnis. Das Resultat gilt es dann aber noch in passenden HTML-Code einzubetten, damit der Browser etwas damit anfangen kann und auch Links funktionieren 2 . Anderenfalls käme keine richtige Interaktion zwischen dem Server und dem Browser zustande. Um eine Auflistung eines Verzeichnisses in HTML-Code umzuwandeln, empfiehlt sich der Einsatz des mächtigen Stream-Editors Sed .

Listing 5 zeigt die Funktionen, die für die Rückgabe des Inhalts des Root-Ordners und auch einzelner Seiten darin sorgen. Die Ausgabe des Verzeichnisinhalts übernimmt in der Funktion list_dir (ab Zeile 1) ein einfacher Ls-Befehl, dessen Resultat Sed dann in lupenreines HTML verwandelt. Die durch die Funktion aus Listing 2 erzeugten Dateien, die im Root-Ordner liegen, enthalten bereits HTML-Code. Der Server gibt sie über die Funktion return_file ab Zeile 19 mit einem passenden Header an den Webbrowser zurück.

Dadurch, dass Netcat in der Schleife fortlaufend für Anfragen zur Verfügung steht und einen Header sowie das passende HTML dazu versendet, meint ein Browser im lokalen Netzwerk, es mit einem echten Webserver zu tun zu haben.

Es kann aber auch der Fall auftreten, dass der Anwender im Browser manuell eine Seite anfordert, die es gar nicht gibt. Das führt zum berüchtigten Fehler 404, den Sie bestimmt schon einmal im Web gesehen haben . Auch der Eigenbau-Webserver kann mit diesem Feature aufwarten. Falls der Cat-Befehl in der ersten Zeile der Funktion return_file (Zeile 20) einen Fehler auslöst, wird der Else-Zweig ab Zeile 28 ausgeführt. Im Webbrowser erscheint dann die Meldung, dass die angefragte Seite nicht existiert.

POST-Anfragen

Im Gegensatz zu GET-Anfragen, bei denen der Webbrowser Dateien heruntergeladen möchte, gibt es auch POST-Anfragen, die ein Browser an einen Webserver senden kann. Stellen Sie sich das so vor, als wollten Sie etwas auf einem Social-Media-Portal posten. Sie geben Text, Bilder oder auch Videos in eine dafür vorgesehene Box ein und drücken anschließend auf Posten. Der jeweilige Inhalt wird dann zum Server hochgeladen und erscheint anschließend auf Ihrem Profil. Unser einfacher Server verfolgt erst einmal nur den Zweck, Dateien von einem Browser aus hochzuladen und im Ordner uploads/ zu speichern.

Weitere Infos und interessante Links

www.raspi-geek.de/qr/47698

Auch hier sendet der Browser einen Header, in dem er angibt, dass er einen Post machen will. Sie können ganz einfach selbst testen, wie so eine Post-Anfrage aussieht, indem Sie das Kommando aus Listing 6 ausführen. Anschließend rufen Sie im Browser das Webformular im Root-Ordner auf und senden eine Datei 3 3 . Nach ein paar Sekunden unterbrechen Sie das Netcat-Kommando mit [Strg]+[C]. Im Browser erscheint die Meldung Datei angekommen, und die Datei befindet sich dort, wohin Sie umgeleitet wurde. Allerdings handelt es sich noch um keine anzeigbare JPEG-Datei, da das gespeicherte File zum Beispiel noch den Header enthält 4 .

Listing 7 zeigt, wie Sed überschüssige Daten wegschneidet, die nicht zu der hochgeladenen Datei gehören. Diese Aufgabe übernimmt der in der While-Schleife ab Zeile 9 enthaltene Code. Er entfernt den Header, Boundary-Angaben, den Dateinamen und Ähnliches. Um zu vergleichen, wie die Daten ursprünglich ausgesehen haben, werfen Sie einen Blick in die Cache-Datei, die sich ebenfalls im Upload-Ordner befindet. Würde Sed nicht alles Unnötige aus dem Datenstrom wegschneiden, könnte das Betriebssystem die empfangenen Dateien nicht korrekt darstellen.

Dateien zum Artikel herunterladen unter

www.raspi-geek.de/dl/47698

Die Routine ruft im Hintergrund zudem die Funktion run_post_server auf (letzte Zeile). Sie enthält eine passende Antwort für POST-Anfragen, die die Länge des Inhalts in Bytes angibt sowie die Informationen enthält, dass nach dem Lesen die Verbindung gekappt werden soll. Ohne diese Angaben würde Firefox die Verbindung einfach halten, obwohl die Daten schon gesendet wurden. Die Funktion startet im Hintergrund (&), damit sie nicht alles blockiert, sobald Dateien gesendet werden.

Ungeprüft

Auch wenn ein Webbrowser nach dem Root-Verzeichnis oder einer anderen Datei fragt, kann der Webserver im Prinzip zurückschicken, was immer Sie wollen – Sie müssen es für den Browser nur entsprechend deklarieren. Ein Beispiel zeigt Listing 8. Der Browser zeigt in diesem Fall beim Aufruf von localhost:8080 oder IP‐Adresse:8080 sofort eine JPEG-Datei an, ohne sich darüber zu beschweren. Interessant daran ist nicht nur, dass das funktioniert: Es stellt auch eine potenzielle Sicherheitslücke dar. Offenbar überprüfen die meisten Webbrowser überhaupt nicht, ob die Anforderung im GET-Request und die zurückgelieferte Seite zusammenpassen. Im diesem Fall hat der Browser nach der Indexseite des Webservers verlangt und stattdessen eine JPEG-Datei erhalten. Das ist etwa so, als würde ein Tennisspieler von seinem Gegenspieler auf einmal mit einem Basketball beworfen.

Erfahrungsgemäß sind solche Eigenheiten und auch andere Features, die man möglicherweise implementieren möchte, im Web nur unzureichend oder auch gar nicht dokumentiert . Deswegen hilft es mitzuschneiden, was Firefox und andere Browser anfragen. Die Funktion aus Listing 9 ist für den Start des Servers verantwortlich. Sie sehen dort zwei tee-Umleitungen, die alle Daten zum Debuggen in eine Log-Datei weiterleiten. In diesem Protokoll finden Sie dann mit Datum und Uhrzeit versehen, was jeweils der Webbrowser als Anfrage gesendet und der Server als Antwort darauf zurückgeschickt hat 5 5 . So können Sie jede Anfrage und Antwort analysieren und nachvollziehen, was genau während der Kommunikation zwischen Client und Server geschieht.

Viele Browser fragen zum Beispiel nach dem berühmten favicon.ico, wenn sie etwas länger mit einem Server kommuniziert haben. Dabei handelt es sich um das Icon, das Sie meist oben in den Tabs der Browser sehen. Es liegt normalerweise im Root-Ordner des Webservers.

Falls Sie möchten, dass auch Ihr Eigenbau-Server ein solches Favicon zur Verfügung stellt, dann müssen Sie erst herausfinden, wie eine entsprechende Anfrage des Browsers aussieht, um dann den Server passend reagieren zu lassen. Dass der Webbrowser des Öfteren nach dieser Datei fragt, können Sie an der Fehlermeldung cat: http_home/favicon. ico: Datei oder Verzeichnis nicht gefunden in der Protokolldatei erkennen. Der Browser fordert die Icon-Datei also eigenständig an.

Fazit

Wie Sie sehen, lässt sich mit einfachen Mitteln schnell ein rudimentärer Webserver zusammenbauen. Der hier vorgestellte ist zwar schlicht und einfach konstruiert, soll aber auch gar nicht mit Boliden wie dem Apache-Webserver oder Nginx konkurrieren. Er besitzt aber Fähigkeiten, die ein typischer Webserver nicht aufweist: Er kann auf das ganze Repertoire von Shell-Befehlen zugreifen und auf diesem Weg mit minimalem Aufwand Informationen lokal im eigenen Netzwerk darstellen. Auch die Ressourcen, die das kleine Skript verbraucht, halten sich in engen Grenzen. Als Info-Server im eigenen Netzwerk kann sich der Eigenbau also sehen lassen, und er taugt auch dazu, Dateien von einem Rechner auf den anderen Rechner zu befördern – insgesamt sicher keine schlechte Lösung für das heimische Netz.

(cla)