SSD Nodes Learn Hosting plans →
Anleitungen Matt ConnorVon Matt Connor

HTTP erklärt: Leitfaden für Serveradministratoren

HTTP für Serveradministratoren erklärt: Methoden, Statuscodes, wichtige Header, nginx-Logs sowie die Rolle von TLS und HTTP/3 im Betrieb.

Was ist HTTP?

HTTP (Hypertext Transfer Protocol) ist ein Regelwerk, mit dem ein Client und ein Webserver Daten anfordern und zurücksenden. Der Client sendet eine Anfrage. Sie enthält eine Methode wie GET, einen Pfad wie /pricing, eine Protokollversion, eine Liste von Headern und manchmal einen Body. Der Server antwortet mit einem Statuscode wie 200, gefolgt von seinen eigenen Headern und normalerweise einem Body. Jeder Seitenaufruf und jeder API-Aufruf (Application Programming Interface) auf Ihrem Server besteht aus genau diesem wiederholten Austausch.

HTTP speichert selbst keinen Zustand. Der Server merkt sich nicht, was Sie vor einer Sekunde angefordert haben. Alles, was sich wie ein Speicher verhält, beispielsweise eine Anmeldesitzung, wird daher bei jeder einzelnen Anfrage in einem Header übertragen. Diese Eigenschaft erklärt vieles, was folgt: Caching wird vollständig über Header gesteuert, und ein Load Balancer kann Ihre nächste Anfrage an ein anderes Backend senden, ohne dass etwas dadurch beeinträchtigt wird.

Im Folgenden wird dieses Modell aus Sicht des Servers beschrieben: in Ihrem Access-Log und in Ihrer nginx-Konfiguration.

Eine rohe Anfrage und Antwort, kommentiert

Hier ist eine vollständige HTTP/1.1-Anfrage. Eine Leerzeile beendet die Header. Alles nach dieser Zeile ist der Body. Ein GET hat normalerweise keinen Body.

GET /pricing HTTP/1.1
Host: example.com
User-Agent: curl/8.5.0
Accept: */*
Accept-Encoding: gzip
  • GET ist die Methode. Sie gibt an, was ausgeführt werden soll. GET liest Daten, POST sendet Daten, PUT ersetzt Daten, DELETE entfernt Daten und HEAD fordert nur die Header eines GET ohne Body an.
  • /pricing ist der Pfad. Der Hostname ist nicht Bestandteil der Request-Zeile. Deshalb gibt es den nächsten Header.
  • HTTP/1.1 ist die Protokollversion, die der Client verwendet.
  • Host: example.com gibt an, welche Website der Client anfordert. HTTP/1.1 verlangt diesen Header. nginx beantwortet eine Anfrage ohne diesen Header daher mit 400 Bad Request.
  • Die übrigen Header enthalten Präferenzen. Accept-Encoding: gzip gibt an, dass der Client Daten dekomprimieren kann. Der Server darf den Body daher komprimieren.

Die Antwort hat dieselbe Struktur, beginnt jedoch mit einer Statuszeile.

HTTP/1.1 200 OK
Date: Thu, 06 Aug 2026 09:12:44 GMT
Server: nginx
Content-Type: text/html; charset=utf-8
Content-Length: 5310
Cache-Control: public, max-age=300

<!doctype html>...
  • 200 OK ist der Statuscode mit seiner Begründungsphrase. Entscheidend ist der Code. Die Phrase dient nur zur Information und wird von Clients ignoriert.
  • Content-Type teilt dem Client mit, wie er die folgenden Bytes behandeln soll.
  • Content-Length gibt die Größe des Bodys in Bytes an. Der Client erkennt dadurch, wo der Body endet. Ist die Größe im Voraus nicht bekannt, sendet der Server stattdessen Transfer-Encoding: chunked und kennzeichnet das Ende mit einem Chunk der Länge null.
  • Cache-Control teilt dem Browser und allen zwischengeschalteten Caches mit, wie lange sie diese Antwort als aktuell behandeln dürfen. Sobald ihr Alter max-age Sekunden überschreitet, ist sie veraltet. Das bedeutet nicht, dass sie gelöscht wurde: Ein Cache kann eine veraltete Kopie behalten und sie bei Ihrem Server erneut validieren, statt den gesamten Body erneut herunterzuladen.
  • Die Leerzeile nach den Headern trennt die Header in beiden Richtungen vom Body.

Headernamen unterscheiden nicht zwischen Groß- und Kleinschreibung. Jede Zeile endet mit einem Carriage Return gefolgt von einem Line Feed und nicht mit einem einfachen Newline. Sie werden diese Zeichen nicht von Hand eingeben. In einem Packet Capture werden sie Ihnen jedoch begegnen.

Um ein echtes Anfrage-Antwort-Paar zu beobachten, führen Sie diesen Befehl gegen eine Website aus, die Ihnen gehört:

curl -sS -o /dev/null -D - https://example.com/

-D - schreibt die Response-Header in Ihr Terminal und -o /dev/null verwirft den Body. Verwenden Sie dies anstelle von curl -I, weil -I eine HEAD-Anfrage sendet. Ein Anwendungsserver, der HEAD anders behandelt als GET, und das tun viele, zeigt Ihnen dann Header, die kein Browser erhält. curl -v gibt beide Seiten aus. Request-Zeilen werden mit > und Response-Zeilen mit < markiert.

So sieht die Request-Zeile in Ihrem nginx access log aus

nginx liefert ein combined-Logformat mit. Dies ist seine Definition:

log_format combined '$remote_addr - $remote_user [$time_local] '
                    '"$request" $status $body_bytes_sent '
                    '"$http_referer" "$http_user_agent"';

Eine davon erzeugte Zeile:

203.0.113.45 - - [06/Aug/2026:09:12:44 +0000] "GET /pricing HTTP/1.1" 200 5310 "https://example.com/" "Mozilla/5.0 (X11; Linux x86_64) Chrome/127.0.0.0 Safari/537.36"
  • 203.0.113.45 ist $remote_addr, die Adresse, von der die TCP-Verbindung (transmission control protocol) geöffnet wurde. Hinter einem Proxy ist dies der Proxy und nicht der Besucher, sofern Sie nicht das weiter unten beschriebene realip-Modul konfiguriert haben, um diesen Wert zu ersetzen.
  • Das erste - ist ein fester Platzhalter. Das zweite ist $remote_user und wird nur bei Verwendung der HTTP-Basisauthentifizierung gefüllt.
  • "GET /pricing HTTP/1.1" ist $request, die vollständige ursprüngliche Request-Zeile. Beim standardmäßigen Log-Escaping von nginx werden ein doppeltes Anführungszeichen, ein Backslash sowie jedes Byte unter 32 oder über 126 als \xXX geschrieben. Die Zeile bleibt dadurch inhaltlich unverändert, entspricht aber nicht immer Byte für Byte dem Original.
  • 200 ist der von Ihrem Server zurückgegebene Status, nicht der vom Besucher wahrgenommene Status.
  • 5310 ist $body_bytes_sent, ausschließlich der Body. Response-Header werden nicht mitgezählt. Dieser Wert ist daher immer kleiner als die tatsächlich gesendete Byte-Anzahl.
  • Die letzten beiden Felder in Anführungszeichen sind Referer und User-Agent. Beide stammen vom Client und können daher beliebige Inhalte enthalten.

Auch ungültige Daten werden in maskierter Form protokolliert. Ein Client, der TLS (transport layer security) an Ihren unverschlüsselten Port 80 sendet, hinterlässt eine 400-Zeile, deren Request-Feld mit maskierten Bytes wie "\x16\x03\x01\x02\x00\x01" beginnt. \x16 ist der Datensatztyp des TLS-Handshake. Diese Bytes sind daher der Anfang eines ClientHello und überhaupt keiner Request-Zeile. Ihr Server verhält sich korrekt. HTTPS wird an einen HTTP-Port gesendet.

Fügen Sie Ihrem Logformat außerdem $server_protocol hinzu. Damit wird HTTP/1.1, HTTP/2.0 oder HTTP/3.0 ausgegeben. Dies ist der schnellste Weg, nachzuweisen, dass eine Protokolländerung tatsächlich wirksam geworden ist.

Bedeutung der häufigsten Statuscodes, wenn Ihre eigene Website sie zurückgibt

Die erste Ziffer gibt die Klasse an. Diese Klasse sollten Sie zuerst lesen.

2xx bedeutet: Die Anfrage war erfolgreich. 200 OK wird bei einem normalen Lesezugriff verwendet. 201 Created folgt auf ein POST, das eine Ressource erstellt hat. 204 No Content steht für einen erfolgreichen Vorgang ohne Antwortinhalt. Das ist die übliche Antwort auf ein DELETE.

3xx bedeutet: Sehen Sie an anderer Stelle nach. 301 ist dauerhaft. Browser speichern diese Weiterleitung hartnäckig, manchmal bis der Benutzer sein Profil löscht. Ein 301 auf den falschen Hostnamen lässt sich daher nur schwer rückgängig machen. Verwenden Sie 302, solange Sie eine Weiterleitung noch testen. 304 Not Modified ist ein Erfolg und kein Fehler: Der Client hat eine bedingte Anfrage gesendet, entweder If-None-Match mit einem ETag (Entity-Tag), das Sie noch erkennen, oder If-Modified-Since mit einem Datum, seit dem sich die Ressource nicht geändert hat. Sie haben daher nur Header und keinen Body zurückgegeben. Viele 304s im Log bedeuten, dass das Caching funktioniert.

4xx bedeutet: Die Anfrage war fehlerhaft. 400 Bad Request steht für eine fehlerhaft formatierte Eingabe. 401 Unauthorized bedeutet tatsächlich, dass keine Authentifizierung vorliegt. Der Statuscode muss einen WWW-Authenticate-Header enthalten, der das Schema angibt. 403 Forbidden bedeutet, dass die Anfrage verstanden, aber trotzdem abgelehnt wurde. 404 Not Found bezeichnet einen Pfad, der nicht existiert oder dessen Existenz der Server nicht bestätigen möchte. Einige Anwendungen geben 404 statt 403 zurück, um eine Ressource vor Clients ohne Zugriffsberechtigung zu verbergen. 405 Method Not Allowed bedeutet, dass der Pfad zwar korrekt ist, aber die Methode nicht unterstützt wird. Das ist beispielsweise die Antwort auf ein POST an eine Position für statische Dateien. 413 bedeutet, dass der Body größer als nginx's client_max_body_size ist. Der Standardwert beträgt 1 Megabyte. Das Error-Log bestätigt dies mit client intended to send too large body.

Ein 403 bei einer statischen Datei weist fast immer auf ein Problem im Dateisystem und nicht auf eine HTTP-Regel hin. Lesen Sie /var/log/nginx/error.log, bevor Sie eine Konfiguration ändern. open() "/srv/site/index.html" failed (13: Permission denied) bedeutet, dass der nginx-Worker-Benutzer die Datei nicht lesen kann. Meist fehlt einem übergeordneten Verzeichnis die Ausführungsberechtigung für andere Benutzer. directory index of "/srv/site/" is forbidden bedeutet, dass der Pfad zu einem Verzeichnis aufgelöst wurde, in dem keine Indexdatei vorhanden ist, während autoindex deaktiviert ist.

5xx bedeutet: Auf Ihrer Seite ist ein Fehler aufgetreten. 500 ist ein allgemeiner Serverfehler. Auf der eigenen Website weist er meist auf einen nicht behandelten Fehler in der Anwendung hin. 502 Bad Gateway bedeutet, dass nginx keine verwendbare Antwort vom Upstream erhalten konnte. Das Error-Log nennt die Ursache: connect() failed (111: Connection refused) while connecting to upstream bedeutet, dass unter der Adresse in proxy_pass kein Prozess auf Verbindungen wartet. 504 Gateway Timeout bedeutet, dass nginx beim Warten auf den Upstream aufgegeben hat. Üblicherweise hat der Upstream die Verbindung angenommen und innerhalb von proxy_read_timeout keine Antwort gesendet. Der Standardwert beträgt 60 Sekunden. Das Log vermerkt dies als upstream timed out (110: Connection timed out) while reading response header from upstream. Wird ein Verbindungsaufbau nicht innerhalb von proxy_connect_timeout abgeschlossen, ebenfalls standardmäßig nach 60 Sekunden, endet er ebenfalls mit 504. Die Logzeile endet dann mit while connecting to upstream. 503 Service Unavailable bedeutet, dass der Server die Anfrage vorübergehend nicht verarbeiten kann. Typische Ursachen sind eine Überlastung oder geplante Wartungsarbeiten. Beachten Sie, dass der eigene Rate Limiter von nginx 503 zurückgibt, weil limit_req_status standardmäßig auf 503 gesetzt ist. Wenn Sie in Ihrem Log nach 429 Too Many Requests suchen, aber stattdessen 503 finden, ist das der Grund. Setzen Sie limit_req_status 429;, um den korrekten Statuscode zu erhalten.

Die relevanten Header beim Betrieb des Servers

Host bestimmt die Website. Eine IP-Adresse kann Hunderte Hostnamen bedienen. nginx gleicht Host mit server_name ab, um zu entscheiden, welcher server-Block antwortet. Wenn nichts übereinstimmt, verwendet nginx den Default-Server. Das ist der erste Block, der an dieser Adresse und diesem Port lauscht, sofern kein anderer als default_server markiert ist. Wenn ein neuer Virtual Host die falsche Website ausliefert, liegt das fast immer daran: Der Name stimmte nicht überein, und die Anfrage fiel auf den Default-Server zurück. Testen Sie dies, ohne DNS zu ändern:

curl -sS -o /dev/null -D - -H 'Host: app.example.com' http://127.0.0.1/

User-Agent ist eine vom Client verfasste Selbstbeschreibung und kann beliebigen Text enthalten. Verwenden Sie ihn beim Auswerten von Logs als Hinweis. Verwenden Sie ihn niemals als Steuerungsmechanismus. Ein Client, der darüber lügen möchte, tut es einfach. Wenn Sie einen Scraper anhand von User-Agent blockieren, treffen Sie daher nur die höflichen Clients.

Content-Type legt fest, wie die Bytes interpretiert werden: application/json für eine API-Anfrage, text/html; charset=utf-8 für eine Seite. nginx ordnet Dateierweiterungen mit /etc/nginx/mime.types den entsprechenden Typen zu. Das mitgelieferte nginx.conf legt default_type application/octet-stream; fest. Eine Datei mit einer Erweiterung, die nginx nicht kennt, wird dadurch als Download angeboten und nicht gerendert. Sichtbar wird das durch eine Seite, die ohne Formatierung geladen wird, während die Browserkonsole Refused to apply style from ... because its MIME type ('text/plain') is not a supported stylesheet MIME type ausgibt. MIME steht hier für Multipurpose Internet Mail Extensions, das Benennungsschema, aus dem diese Typzeichenfolgen stammen.

Cache-Control steuert jeden Cache zwischen Ihrem Server und dem Leser. public, max-age=31536000, immutable eignet sich für Ressourcen, deren Dateiname einen Inhalts-Hash enthält. Der Name ändert sich, sobald sich der Inhalt ändert. no-store gehört zu allen Inhalten, die benutzerspezifisch sind. Ein gemeinsam genutzter Cache, der eine angemeldete Seite speichert, würde sie der nächsten Person ausliefern, die dieselbe URL anfordert. private ist die mittlere Einstellung: Der Browser darf die Antwort speichern, ein gemeinsam genutzter Cache jedoch nicht.

X-Forwarded-For wird benötigt, weil ein Proxy den Besucher verbirgt. Sobald eine Anfrage einen Reverse Proxy durchläuft, ist $remote_addr die Adresse des Proxys. Ihre Logs, Ihre Geolokalisierung und Ihr Rate Limiting sehen dann nur einen Client, bis Sie die ursprüngliche Adresse wiederherstellen. Der Proxy muss die ursprüngliche Adresse weitergeben:

proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;

Dem empfangenden Server muss anschließend mitgeteilt werden, dass er dieser Adresse vertrauen darf. Außerdem muss genau festgelegt werden, welchen Absendern er vertraut:

set_real_ip_from 10.0.0.0/8;
real_ip_header X-Forwarded-For;

Diese beiden Direktiven gehören zum nginx-Modul realip. Es ersetzt $remote_addr durch die weitergeleitete Adresse und speichert die eigene Verbindungsadresse in $realip_remote_addr. Wenn Sie nginx selbst kompilieren, fügen Sie --with-http_realip_module hinzu, da das Modul standardmäßig nicht eingebaut wird.

Listen Sie nur Bereiche auf, die Sie kontrollieren. X-Forwarded-For ist einfacher Text, den jeder Client senden kann. set_real_ip_from 0.0.0.0/0; ermöglicht es einem Besucher daher, die geloggte Adresse und die vom Rate Limiting gezählte Adresse selbst festzulegen.

X-Forwarded-Proto verhindert einen bestimmten und sehr häufigen Fehler. Ihr Proxy beendet TLS und leitet die Anfrage über einfaches HTTP an die Anwendung weiter. Die Anwendung sieht eine unverschlüsselte Anfrage, entscheidet, dass der Besucher HTTPS verwenden sollte, und antwortet mit 301 https://example.com/. Der Browser folgt dieser Antwort. Der Proxy beendet TLS erneut und leitet wieder einfaches HTTP weiter. Die Schleife wiederholt sich, bis der Browser mit ERR_TOO_MANY_REDIRECTS aufgibt. Wenn Sie X-Forwarded-Proto: https senden, weiß die Anwendung, dass der Besucher bereits HTTPS verwendet. Sie beendet dann die Weiterleitungen.

HTTP/1.1 vs. HTTP/2 vs. HTTP/3: Was sich für Sie ändert

HTTP/1.1 ist textbasiert und verarbeitet in der Praxis pro Verbindung jeweils eine Anfrage. Connection: keep-alive ermöglicht es der nächsten Anfrage, dieselbe TCP-Verbindung wiederzuverwenden. Dadurch entfällt der Aufwand für den Verbindungsaufbau. Antworten werden jedoch weiterhin in der Reihenfolge ihrer Anfragen zurückgegeben. Das Protokoll erlaubt außerdem Pipelining. Dabei sendet ein Client mehrere Anfragen, ohne auf die Antworten zu warten. Die Reihenfolgeregel gilt trotzdem. Kein moderner Browser aktiviert Pipelining standardmäßig. Eine langsame Antwort blockiert alles, was dahinter wartet. Das ist Head-of-Line-Blocking. Browser umgehen es, indem sie gleichzeitig mehrere Verbindungen zu demselben Hostnamen öffnen.

HTTP/2 verwendet weiterhin dieselben Methoden und Statuscodes, ändert aber die Rahmung in ein Binärformat. Viele Anfragen teilen sich eine Verbindung als unabhängige Streams. Wiederholter Header-Text wird komprimiert. Das ist relevant, weil moderne Anfragen viele Header enthalten. Die Verbindung verwendet weiterhin TCP. Deshalb hält ein verlorenes Paket jeden Stream auf dieser Verbindung an, bis die erneute Übertragung eintrifft. Das Head-of-Line-Blocking ist nicht verschwunden. Es ist von HTTP in die Transportschicht verschoben worden. Server Push war Bestandteil von HTTP/2 und wird in der Praxis nicht mehr verwendet, weil Chrome die Unterstützung dafür 2022 entfernt hat.

HTTP/3 behält erneut dieselbe Semantik bei und ersetzt TCP durch QUIC, ein auf UDP (User Datagram Protocol) basierendes Transportprotokoll. QUIC-Streams sind bis in die untersten Schichten unabhängig. Deshalb hält ein verlorenes Paket nur den Stream an, zu dem es gehörte. TLS 1.3 ist in den QUIC-Handshake integriert, statt darübergelegt zu werden. Eine neue Verbindung benötigt dadurch weniger Roundtrips. Daraus ergeben sich zwei praktische Konsequenzen: Der UDP-Port, den Ihr Server für HTTP/3 verwendet, muss in jeder Firewall auf dem Übertragungsweg geöffnet sein. Außerdem führen Netzwerke, die UDP drosseln oder blockieren, dazu, dass Clients auf HTTP/2 zurückfallen. Dieser Port ist normalerweise 443. Das Protokoll erlaubt einem Server jedoch, jeden UDP-Port zu verwenden, weil die Ankündigung, die Browser auf HTTP/3 verweist, den Port immer ausdrücklich nennt.

Was sich für Sie konkret ändert: Browser beginnen normalerweise nicht mit HTTP/3. Sie verbinden sich über HTTP/2 oder HTTP/1.1, sehen im Response einen Alt-Svc: h3=":443"; ma=86400-Header und verwenden HTTP/3 bei späteren Verbindungen zu diesem Host. Eine Ausnahme ist ein HTTPS-Record im DNS, dessen Wert alpn h3 auflistet. Dadurch kann ein Browser wie Firefox HTTP/3 bereits bei der ersten Verbindung öffnen. Dieser Record ist ein zusätzlicher Hinweis und kein Ersatz. Der Header ist daher keine optionale Dekoration. Er ist der wichtigste Mechanismus zur Erkennung. In nginx wurde HTTP/2 ab Version 1.25.1 zu einer eigenen Direktive (http2 on; innerhalb des server-Blocks; sie ersetzt den alten listen ... http2-Parameter). QUIC kam in der Mainline-Version 1.25.0 hinzu. Für eine HTTP/3-Site benötigt nginx dort zusätzlich zu listen 443 ssl; das listen 443 quic reuseport;. Das HTTP/3-Modul wird standardmäßig nicht gebaut (--with-http_v3_module). Die nginx-Dokumentation bezeichnet die Unterstützung weiterhin als experimentell.

Proxies unterscheiden sich bei der Reife dieser Unterstützung. Prüfen Sie daher die Version, die Sie tatsächlich einsetzen. Stand November 2026 stellt Caddy HTTP/3 ohne Konfiguration standardmäßig bereit. nginx benötigt den expliziten quic-Listener sowie den oben beschriebenen Alt-Svc-Header. Traefik aktiviert HTTP/3 pro Entry Point über eine ausdrückliche http3-Option. Wenn Sie TLS mit Traefik vor mehreren Docker-Anwendungen terminieren, wird die von Ihren Besuchern verwendete Protokollversion dort festgelegt. Der Hop vom Proxy zu Ihrem Container verwendet unabhängig von der Aushandlung durch den Browser normalerweise einfaches HTTP/1.1.

Prüfen Sie die tatsächliche Aushandlung, statt sie vorauszusetzen. curl --http3 -sS -o /dev/null -D - https://example.com/ funktioniert nur, wenn curl -V HTTP3 in seinen Features auflistet. Die meisten Distributions-Builds enthalten diese Unterstützung nicht. Die zuverlässige Prüfung erfolgt über Ihr eigenes Log. Fügen Sie dem Format $server_protocol hinzu und lesen Sie, welches Protokoll echte Browser aushandeln. Prüfen Sie vorher, ob der UDP-Port Ihres quic-Listeners, in der obigen Konfiguration 443, tatsächlich geöffnet ist. Eine Firewall, die nur TCP 443 erlaubt, lässt HTTP/3 unbemerkt fehlschlagen, während die Site weiterhin über HTTP/2 funktioniert. Zu wissen, welche Ports auf Ihrem Linux-Server geöffnet sind und auf Verbindungen warten, ist der erste Prüfschritt.

HTTPS: HTTP ist das Protokoll, TLS ist die Verschlüsselung

HTTPS ist kein separates Protokoll. Es handelt sich um dieselben Anfragen und Statuscodes, die innerhalb einer TLS-Sitzung übertragen werden. Port 80 überträgt sie unverschlüsselt, Port 443 verschlüsselt. Zuerst wird der TLS-Handshake abgeschlossen. Danach wird die HTTP-Anfrage innerhalb des verschlüsselten Kanals übertragen. Deshalb ist einem Zertifikatsproblem niemals ein Statuscode zugeordnet: Der Fehler tritt auf, bevor auch nur ein einziges HTTP-Byte gesendet wurde. Daher gibt es keine nummerierte Antwort.

Auf einem Server, der mehrere Websites hostet, ist die Reihenfolge wichtig. Das Zertifikat wird anhand von SNI (Server Name Indication) ausgewählt. Dabei handelt es sich um ein Feld im TLS-Handshake, das den Hostnamen unverschlüsselt überträgt, bevor ein HTTP-Header vorhanden ist. Der Server wählt daher zuerst anhand von SNI ein Zertifikat und anschließend anhand des Headers Host einen virtuellen Host. Das sind zwei getrennte Zuordnungen, die normalerweise übereinstimmen. Wenn sie es nicht tun, zeigt der Browser einen Namenskonflikt wie NET::ERR_CERT_COMMON_NAME_INVALID an und sendet überhaupt keine Anfrage, weil das Zertifikat Ihres Standardservers für einen Namen angeboten wurde, den es nicht abdeckt.

Für eine öffentliche Website sollten Sie ein gültiges Zertifikat beziehen und automatisch erneuern lassen. Certbot mit Let's Encrypt unter nginx trägt die Zertifikatspfade in Ihren Server-Block ein und richtet den Erneuerungs-Timer für Sie ein. Für einen Hostnamen, den keine öffentliche Zertifizierungsstelle validieren kann, etwa einen internen Namen oder eine nicht weiter spezifizierte IP-Adresse in Ihrem eigenen Netzwerk, ist ein selbst signiertes Zertifikat unter Ubuntu die sachgerechte Option. Sie müssen dann allerdings jedem Client mitteilen, dass er diesem Zertifikat vertrauen soll.

Sobald TLS funktioniert, leiten Sie alles von Port 80 an Port 443 weiter:

server {
    listen 80;
    server_name example.com;
    return 301 https://$host$request_uri;
}

Fügen Sie Strict-Transport-Security nur hinzu, wenn Sie sicher sind. Der Header add_header Strict-Transport-Security "max-age=63072000; includeSubDomains" always; weist Browser an, für diesen Hostnamen zwei Jahre lang kein unverschlüsseltes HTTP zu verwenden. Sie befolgen diese Vorgabe aus ihrem eigenen Cache. Das bedeutet, dass das spätere Entfernen des Headers die Einstellung nicht rückgängig macht. Beginnen Sie mit einem max-age von einigen Stunden. Prüfen Sie, ob wirklich jede Subdomain HTTPS verwendet, und erhöhen Sie den Wert anschließend.

FAQ

Was ist der Unterschied zwischen HTTP und HTTPS?

HTTPS ist HTTP, das innerhalb einer TLS-Sitzung (Transport Layer Security) übertragen wird. Die Methoden und Statuscodes sind identisch. Geändert wird, dass die Bytes zwischen dem Client und dem TLS-Terminierungspunkt verschlüsselt sind und der Standardport von 80 auf 443 wechselt. Da der TLS-Handshake abgeschlossen wird, bevor das erste HTTP-Byte gesendet wird, erzeugt ein Zertifikatsfehler niemals einen Statuscode. Deshalb zeigt eine Zertifikatswarnung im Browser einen Fehlernamen wie NET::ERR_CERT_COMMON_NAME_INVALID statt einer Zahl wie 403.

Warum gibt meine Website 502 Bad Gateway zurück?

Ein 502 von nginx bedeutet, dass nginx keine verwendbare Antwort vom Upstream erhalten konnte, an den es weiterleitet. Die Anfrage des Besuchers war also in Ordnung, aber etwas hinter nginx nicht. Lesen Sie /var/log/nginx/error.log. connect() failed (111: Connection refused) while connecting to upstream bedeutet, dass unter der Adresse und dem Port in proxy_pass kein Prozess lauscht. Prüfen Sie daher, ob die Anwendung läuft und an die erwartete Adresse gebunden ist. no live upstreams while connecting to upstream bedeutet, dass jeder Server im Upstream-Block nach wiederholten Fehlern als ausgefallen markiert wurde. Vergleichen Sie dies mit 504 Gateway Timeout. Dieser Status bedeutet, dass nginx beim Warten auf den Upstream eine Zeitüberschreitung hatte, entweder beim Herstellen der Verbindung innerhalb von proxy_connect_timeout oder beim Warten auf eine Antwort innerhalb von proxy_read_timeout.

Warum zeigt mein Access-Log für jeden Besucher dieselbe IP-Adresse?

Weil $remote_addr die Adresse des Hosts protokolliert, der die TCP-Verbindung geöffnet hat. Hinter einem Reverse Proxy oder einem Content Delivery Network ist das die Adresse des Proxys. Die Adresse des Besuchers steht stattdessen im Header X-Forwarded-For. Setzen Sie proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; auf dem Proxy. Setzen Sie auf dem empfangenden nginx anschließend set_real_ip_from auf den Adressbereich des Proxys und real_ip_header X-Forwarded-For;. Führen Sie nur Bereiche auf, die Sie kontrollieren. Dieser Header enthält Text, den jeder Client senden kann. Wenn Sie ihm aus dem gesamten Internet vertrauen, kann ein Besucher die protokollierte Adresse und die Adresse für das Rate-Limiting selbst festlegen.

Muss ich HTTP/2 oder HTTP/3 aktivieren?

HTTP/2 sollten Sie aktivieren. Bei einer Website mit bereits eingerichtetem TLS genügt dafür eine Direktive. Außerdem entfällt die Beschränkung der Anfragen pro Verbindung, durch die Seiten mit vielen kleinen Dateien langsam werden. HTTP/3 bietet einen geringeren und weniger sicheren Vorteil. Dafür benötigen Sie einen offenen UDP-Port, normalerweise 443, sowie einen Proxy-Build mit QUIC-Unterstützung. Beachten Sie, dass Browser normalerweise erst dann auf HTTP/3 wechseln, wenn sie in einer früheren Antwort einen Alt-Svc-Header sehen oder einen HTTPS-DNS-Eintrag mit h3 erhalten. Ohne einen dieser Einträge ändert sich nichts, unabhängig davon, was in Ihrer listen-Zeile steht. Fügen Sie $server_protocol Ihrem Log-Format hinzu und messen Sie, welches Protokoll Besucher tatsächlich aushandeln, bevor Sie Zeit darauf verwenden.

Was bedeutet 403 Forbidden, wenn die Datei vorhanden ist?

Auf einer statischen Website weist ein 403 meistens auf ein Dateisystem-Berechtigungsproblem und nicht auf eine HTTP-Regel hin. open() ... failed (13: Permission denied) in /var/log/nginx/error.log bedeutet, dass der nginx-Worker-Benutzer die Datei nicht lesen kann. Meistens fehlt einem übergeordneten Verzeichnis die Ausführungsberechtigung für andere Benutzer, nicht der Datei selbst eine passende Dateiberechtigung. directory index of ... is forbidden bedeutet, dass die Anfrage zu einem Verzeichnis ohne Indexdatei aufgelöst wurde, während autoindex deaktiviert ist. Eine explizite deny-Regel im passenden location-Block gibt ebenfalls 403 zurück. Lesen Sie diesen Block, wenn das Error-Log keinen Hinweis enthält.

War dieser Artikel hilfreich?

#http#https#web-server#headers#http3