11.7 Das World Wide Web
Die wichtigste Dienstleistung des Internets ist das World Wide Web (WWW). Natürlich können Sie auch und gerade unter Linux eigene Webserver aufsetzen und nutzen. Im Folgenden beschreiben wir die Verwendung des Webservers NGINX, eine der meistgenutzten Webserversoftwares des Internets.
11.7.1 Das HTTP-Protokoll
Zuvor allerdings noch etwas Theorie. Viele Menschen setzen das World Wide Web mit dem Internet gleich – dem ist aber nicht so. Das Internet ist einfach ein großes Netzwerk sehr vieler, über die ganze Welt verteilter Computer. Wenn man aber vom World Wide Web spricht, dann meint man meist die Gesamtheit aller HTTP-Dienste (Hypertext Transfer Protocol) des Internets – also alles, was man sich mit einem Browser anschauen kann. Dass in einem Netzwerk aber noch viel, viel mehr Dienste angeboten werden können, wissen Sie spätestens seit diesem Kapitel.
Um eine Webseite oder gar einen ganzen Internetauftritt zur Verfügung zu stellen, brauchen Sie logischerweise auch einen Serverdienst – in unserem Fall eben den NGINX. Der Webbrowser als Client baut wie gewohnt eine Verbindung zum Server auf und bekommt von diesem die Seite.
Interessant sind einige Besonderheiten des HTTP-Protokolls. Es gibt nämlich in einem gewissen Sinne keine Verbindungen: Wenn ein Client sich verbindet, wird die TCP-Verbindung im Allgemeinen nach dem Senden der Seite wieder unterbrochen. Damit hat der Webserver keine Möglichkeit, festzustellen, ob sich ein Benutzer eingeloggt hat oder neu auf der Seite ist. Man benötigt daher einige Tricks, um solche Sessions zu ermöglichen.
Cookies und Co.
Ein Weg ist einfach: Wenn sich ein Benutzer einloggt, wird jedes Mal eine eindeutige ID mitgeschickt. Damit kann eine dynamische Seite feststellen, zu welcher Session ein Request gehört, und dementsprechend die Seite erzeugen. Was bedeutet dynamisch? Standardmäßig sind Seiten nur statisch, da HTML eine Seitenbeschreibungssprache ist und keine dynamischen Inhalte ermöglicht. Dynamische Sprachen wie PHP oder ASP.NET erzeugen HTML-Seiten. Sie ermöglichen es, Inhalte dynamisch zu gestalten und trotzdem für den Client kompatibel zu bleiben.
Eine andere Möglichkeit, Sessions zu verfolgen, sind Cookies – kleine Speicher auf dem Rechner des Nutzers oder der Nutzerin, die mit Informationen befüllt werden können, um beim nächsten Besuch wieder nutzerfreundlicher mit dem Server agieren zu können. Zu Recht haben Cookies bei Anwenderinnen und Anwendern einen schlechten Ruf und sind oft deaktiviert, sofern möglich. Cookies werden nämlich auch genutzt, um Ihr Surfverhalten zu analysieren, sodass personalisierte Werbung für Sie auf Webseiten platziert werden kann. Nicht jeder möchte das.
HTTP im Überblick
Aber schauen wir uns einmal im Detail an, was bei einem HTTP-Request übertragen wird. Wir nutzen dazu das Programm telnet, das ja nicht nur Client eines Login-Dienstes ist, sondern sich auch mit anderen Ports verbinden kann. Bei einer solchen Anwendung wird die Eingabe des Benutzers unverändert gesendet beziehungsweise die Ausgabe des Servers auf dem Bildschirm dargestellt – ideal also zum Testen von Protokollen.
$ telnet www.gmx.de 80 Trying 82.165.229.152... Connected to redir.g-ha-web.de. Escape character is '^]'. GET / HTTP/2.0 (Return) Host: gmx.de (Return) (Return) HTTP/1.1 301 Moved Permanently Date: Fri, 26 Apr 2024 14:44:11 GMT Server: Apache Location: https://www.gmx.net/ Content-Length: 228 Connection: close Content-Type: text/html; charset=iso-8859-1 <!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN» <html><head> <title>301 Moved Permanently</title> … Connection closed by foreign host.
Listing 11.41 Senden eines HTTP-Requests zum Abrufen einer Seite
An diesem Beispiel haben wir Folgendes gesehen:
-
DNS
Zuerst wird der Hostname in eine IP-Adresse umgewandelt, damit man sich überhaupt gemäß TCP/IP verbinden kann. -
Der Client ist passiv
Der im HTTP-Protokoll vorgesehene Befehl GET zum Anfordern einer Seite wird vom Client – in unserem Fall nicht durch den Browser, sondern durch den Benutzer bzw. die Benutzerin – geschickt. Dabei verhält sich der Client passiv und wartet auf die Seite. Außerdem haben wir über den Hostheader angegeben, welche Webseite/Domain wir bekommen wollen. Schließlich könnten auf einer IP bzw. in einem Webserver mehrere Domains bereitgestellt werden. -
Serverantwort
Der Server stellt die Seite aktiv zur Verfügung. Dabei schickt er einige Informationen über sich mit den puren HTML-Daten, die den Aufbau der eigentlichen Seite beschreiben. -
HTTP ist unverschlüsselt
Wie Sie sehen, wird alles im Klartext übertragen – die Befehle des Protokolls genauso wie die Daten an sich. Wird eine Leitung abgehört, kann ein Hacker also ohne Weiteres die Seiten mitlesen, die Sie gerade laden. Zum sicheren Übertragen gibt es das sogenannte HTTPS-Protokoll, das einen gewissen Schutz bietet.
So viel zur Terminologie. Einige Begriffe werden Sie zwar schon gehört haben, aber in diesem Kontext war eine Erläuterung noch einmal wichtig.
11.7.2 Einrichten eines NGINX-Webservers
Kommen wir nun zu dem mit Abstand interessantesten Teil – zur Konfiguration eines eigenen HTTP-Servers. Auch wenn Sie nicht gerade Provider sein wollen, kann ein eigener Webserver für Sie praktisch sein. Vor allem wenn Sie Ihre eigene Website basteln möchten, werden Sie den Nutzen eines eigenen Servers schätzen lernen.
Als eigenen Webserver empfehlen wir dabei den NGINX – einer der im Internet am weitesten verbreiteten Webserver. Aus diesem Grund ist es ziemlich wahrscheinlich, dass Ihre Distribution bereits ein NGINX-Paket enthält.
Der Grund dafür, dass NGINX so erfolgreich ist, liegt sicherlich in seinen Eigenschaften: NGINX ist bekannt dafür, performant zu sein und gleichzeitig vergleichsweise wenig Ressourcen zu benötigen.
Die nginx.conf
Im Folgenden wollen wir den NGINX konfigurieren (Sie installieren ihn zuvor natürlich über das Paketverwaltungstool Ihrer Distribution). Dazu editieren wir die nginx.conf, die sich meistens im Verzeichnis /etc/nginx befindet. Die Datei ist unter Umständen sehr groß – kein Wunder bei einer so wichtigen und umfangreichen Software. Falls die Datei bei Ihnen recht klein ist, wird es wahrscheinlich mehrere Include-Anweisungen geben, die andere Konfigurationsdateien in diese Datei einbinden. Durch diesen Mechanismus kann man die Konfiguration aufteilen und damit gegebenenfalls übersichtlicher gestalten. Außerdem können (und sollten) lokale Änderungen nicht in der nginx.conf selbst, sondern in einer eigenen Datei aus dem Include-Verzeichnis vorgenommen werden. Die Hauptdatei kann dann überdies vom Paketverwaltungstool der Distribution verwaltet und gegebenenfalls aktualisiert werden.
Wir werden die wichtigsten Optionen im Folgenden erläutern.
user nginx; worker_processes auto; error_log /var/log/nginx/error.log; pid /var/run/nginx.pid; events { worker_connections 1024; } http { include /etc/nginx/mime.types; default_type application/octet-stream; access_log /var/log/nginx/access.log; sendfile on; tcp_nopush on; tcp_nodelay on; include /etc/nginx/conf.d/*.conf; server { listen 80; server_name ihre-domain.xyz; location / { root /usr/share/nginx/html; index index.html; } } }
Listing 11.42 Die nginx.conf
In diesem Beispiel läuft der NGINX als Benutzer nginx. Außerdem legt NGINX die Anzahl der Arbeitsprozesse, die HTTP-Requests bearbeiten, selbstständig anhand der verfügbaren CPU-Cores fest (worker_processes auto).
Ein Error-Logfile wird nach /var/log/nginx/error.log geschrieben, weiter unten wird angegeben, dass ein Access-Log (mit allen HTTP-Requests) nach /var/log/nginx/access.log geschrieben werden soll. In der Datei /var/run/nginx.pid steht nach dem Start die Prozess-ID (PID) des Hauptprozesses – NGINX kann so unter anderem erkennen und verhindern, dass der Dienst aus Versehen mehrfach gestartet wird.
Der events-Block definiert alle Einstellungen rund um Verbindungen und Events, in unserem Beispiel wird die maximale Anzahl an HTTP-Verbindungen definiert (worker_connections).
Der http-Block dagegen enthält alle HTTP-Server-Settings. So werden hier unter anderem via sendfile, tcp_nopush und tcp_nodelay verschiedene Performanceoptimierungen aktiviert.
In der nächsten Zeile werden Includes definiert: Es sollen alle Dateien aus dem Verzeichnis /etc/nginx/conf.d/, die auf .conf enden, in die aktuelle Konfiguration eingebettet werden.
Was könnte in solchen Include-Dateien stehen? Typischerweise könnte man spezielle server-Blöcke definieren, ganz so, wie wir hier einen als Beispiel eingefügt haben. Ein solcher Block definiert, wie sich NGINX verhält, wenn (wie in unserem Beispiel konfiguriert) ein HTTP-Request auf Port 80 mit dem Hostheader ihre-domain.xyz ankommt. In diesem Fall werden die Dateien unter /usr/share/nginx/html bereitgestellt, wobei die index.html als Default bereitgestellt wird, wenn keine besondere Datei angefordert wird. Wichtig ist, dass der am Anfang der Datei angegebene Benutzer (in unserem Fall nginx) auch wenigstens Leserechte auf diese Datei hat.
11.7.3 Den NGINX verwalten
Natürlich muss man einen Serverdienst wie den NGINX auch zur Laufzeit verwalten können.
Konfiguration überprüfen
Der NGINX kann seine Konfigurationsdatei mittels der Kommandozeilenoption -t auch selbst überprüfen. Dies ist sinnvoll, wenn Sie beispielsweise Änderungen an einem Produktivsystem vorgenommen haben und vor einem Neustart des Dienstes auf Fehler prüfen wollen, um Ausfälle zu vermeiden.
# nginx -t nginx: the configuration file /etc/nginx/nginx.conf syntax is ok nginx: configuration file /etc/nginx/nginx.conf test is successful
Listing 11.43 nginx -t
Ist die nginx.conf fehlerhaft, wird der entsprechende Fehler angegeben. Mit dieser Hilfe können Sie das Problem dann oft recht einfach und schnell beheben. Nach einer eventuellen Änderung an der nginx.conf können Sie den NGINX dann typischerweise via systemctl neu starten:
# systemctl restart nginx
Listing 11.44 NGINX neu starten
Die Logdateien
Standardmäßig unterstützt der NGINX in zwei unterschiedliche Logdateien. Die access.log wird zur Protokollierung einzelner Zugriffe genutzt, in die error.log werden dagegen nur Fehler geschrieben.
Beide Dateien befinden sich oft in einem Unterverzeichnis unter /var/log beziehungsweise unter /var/log/nginx/.
10.110.101.204 - - [01/May/2024:19:53:27 +0000] "GET /index.html HTTP/1.1" 200 10 "-" "-"
Listing 11.45 Eine Zeile aus der access.log
Hier sehen Sie eine Zeile aus der access.log. Sie können ablesen, dass eine Anfrage von der IP-Adresse 10.110.101.204 gestellt wurde, und zwar am 1. Mai 2024 um 19:53 Uhr. Dieser Client sendete einen GET-Request und wollte dabei die Datei index.html abfragen.
Entsprechende Fehlermeldungen werden dagegen im error.log protokolliert. Ein Blick in diese Datei hilft oft beim Auffinden von Fehlern. Insbesondere bei der Entwicklung eigener Webseiten ist dies hilfreich.