Direkt zum Inhalt

Cookie-Einstellungen

Wählen Sie, welche Arten von Cookies Sie erlauben. Sie können Ihre Auswahl jederzeit über Cookie-Einstellungen unten auf jeder Seite ändern. Datenschutzerklärung

Notwendig

Immer aktiv

Nötig zum Einloggen, für Ihren Warenkorb und um Ihre Auswahl zu speichern. Diese sind immer aktiv.

Welche Cookies?
  • weboke_sessie, weboke_klant, weboke_remember: Ihre Sitzung und eingeloggt bleiben
  • weboke_basket: Ihr Warenkorb
  • wkBtwIncl: Preise mit oder ohne MwSt. anzeigen
  • wok_cookies: Ihre Cookie-Auswahl, 12 Monate

Misst, welche Anzeige zu einem Besuch oder einer Bestellung führt, damit wir nicht für Anzeigen zahlen, die nichts bringen.

Welche Cookies?
  • Google Ads über Google Tag Manager (_gcl_au, _gcl_aw), bis zu 90 Tage
  • OpenAI Ads, Anzeigen in ChatGPT
  • wok_aff: über welchen Partner Sie zu uns kamen (Partnerprogramm), 60 Tage

4,6

Land und Sprache

Jedes Land hat seine eigene Website, mit Preisen und MwSt. dieses Landes.

Anzeigen

Modul 7 · 7.4

Caddy, HSTS und security.txt

Modul 7: Domain, Webserver und https · Lesezeit: 12 Minuten

Lernziel: Nach dieser Lektion können Sie Caddy als einfachen Webserver mit automatischem https nutzen, HSTS und die wichtigsten Sicherheitsheader setzen (in Caddy und nginx), ohne Ihre Website unerreichbar zu machen, und eine gültige security.txt veröffentlichen.

Kernbegriffe: Caddy, Caddyfile, automatisches https, reverse_proxy, file_server, header, HSTS (Strict-Transport-Security), max-age, includeSubDomains, preload, X-Content-Type-Options, frame-ancestors, Referrer-Policy, security.txt, Contact, Expires, /.well-known/

Caddy: https ohne Nachdenken

In Lektion 7.2 und 7.3 haben Sie mit nginx und certbot eine Website mit https aufgebaut. Das sind zwei Programme, ein paar Dateien und ein Timer. Caddy erledigt alles in einem: Es ist ein Webserver mit eingebautem ACME-Client. Steht ein Name in der Konfiguration, zeigt dieser auf den Server und sind Port 80 und 443 erreichbar, dann holt Caddy selbst ein Zertifikat, erneuert es rechtzeitig und leitet http auf https um.

Caddy ist in den Paketquellen von Debian und Ubuntu enthalten (in einer etwas älteren Version); die Entwickler bieten außerdem eine eigene apt-Quelle mit der neuesten Version an, mit eigenem Schlüssel und Signed-By wie in Lektion 4.1. In Modul 9 läuft Caddy als Container für Ihre Docker-Dienste (Lektion 9.4). Hier nutzen Sie ihn als gewöhnlichen Dienst.

anna@web1:~$ sudo apt install caddy
anna@web1:~$ systemctl status caddy

Verwenden Sie entweder nginx oder Caddy auf Port 80 und 443, nicht beide: Nur ein Programm kann auf einem Port lauschen.

Die Caddyfile

Die Konfiguration steht in /etc/caddy/Caddyfile. Eine statische Website und eine Anwendung hinter einem Reverse Proxy:

example.com, www.example.com {
	root * /var/www/example.com
	file_server
	encode zstd gzip
}

app.example.com {
	reverse_proxy 127.0.0.1:3000
}

Das ist alles. Caddy lauscht automatisch auf IPv4 und IPv6, beantragt Zertifikate für die drei Namen, leitet http auf https um und gibt bei reverse_proxy die Header X-Forwarded-For und X-Forwarded-Proto automatisch weiter (was Sie in nginx von Hand erledigt haben, Lektion 7.2).

Testen und Neuladen funktioniert wie bei nginx:

anna@web1:~$ caddy validate --config /etc/caddy/Caddyfile
Valid configuration
anna@web1:~$ sudo systemctl reload caddy
anna@web1:~$ sudo journalctl -u caddy -f

Im Journal sehen Sie, wie die Zertifikate abgerufen werden. Geht etwas schief, steht dort der Grund: meist derselbe wie bei certbot (Port 80 geschlossen, Name zeigt woanders hin, IPv6 defekt; Lektion 7.3).

HSTS: Der Browser merkt sich, dass es https ist

Die Umleitung von http auf https hat einen schwachen Moment: Die allererste Anfrage über http geht noch unverschlüsselt. Jemand im selben Netzwerk kann sie abfangen und den Besucher auf http festhalten. HSTS (HTTP Strict Transport Security, RFC 6797) löst dieses Problem. Ihre Website sendet über https diesen Header mit:

Strict-Transport-Security: max-age=31536000

Der Browser merkt sich dann ein Jahr lang (31.536.000 Sekunden), dass dieser Name nur über https erreichbar sein darf. Tippt der Besucher später http:// ein, macht der Browser selbst https daraus, noch bevor etwas über das Netzwerk geht. Einen HSTS-Header, der über http ankommt, ignoriert der Browser; er zählt nur über https.

Es gibt eine Kehrseite. Hat sich ein Browser HSTS gemerkt und sieht er einen Zertifikatsfehler (abgelaufen, falscher Name), bekommt der Besucher keine Schaltfläche, um trotzdem fortzufahren. Ihre Website ist für diese Besucher dann unerreichbar, bis das Zertifikat stimmt. Deshalb gilt:

  1. Aktivieren Sie HSTS erst, wenn https überall funktioniert und die Erneuerung automatisch läuft (Lektion 7.3).
  2. Beginnen Sie mit einem kurzen max-age, zum Beispiel einem Tag (86400), und erhöhen Sie schrittweise auf ein Jahr.
  3. Seien Sie vorsichtig mit includeSubDomains: Das gilt für jede Subdomain, auch für eine alte Subdomain mit einem Gerät oder Dienst ohne gültiges Zertifikat.
  4. preload beantragt die Aufnahme in eine Liste, die fest in Browser eingebaut ist (hstspreload.org). Dafür verlangen die Betreiber unter anderem ein max-age von mindestens einem Jahr, includeSubDomains und https auf allen Subdomains. Die Entfernung dauert Monate. Tun Sie das nur, wenn Sie sicher sind, dass die gesamte Domain dauerhaft https ist.

Die anderen Sicherheitsheader

Neben HSTS gibt es einige Header, die mit wenig Aufwand viel bewirken:

HeaderSchützt vorWert für den Anfang
X-Content-Type-Optionsder Browser rät, was eine Datei ist, sodass ein hochgeladenes "Bild" als Skript ausgeführt werden kannnosniff
Content-Security-Policy: frame-ancestors (oder das ältere X-Frame-Options)Clickjacking: Eine andere Website lädt Ihre Seite unsichtbar in einem Frameframe-ancestors 'self' (oder X-Frame-Options: SAMEORIGIN)
Referrer-Policydie Adresse Ihrer Seite (mit Suchbegriffen oder Bestellnummern) gelangt an andere Websitesstrict-origin-when-cross-origin

Eine vollständige Content-Security-Policy (welche Skripte und Stile geladen werden dürfen) ist für jede Website Maßarbeit und gehört nicht zu diesem Kurs; beginnen Sie nur mit frame-ancestors.

In Caddy setzen Sie die Header mit der header-Direktive im Block einer Website:

example.com, www.example.com {
	root * /var/www/example.com
	file_server
	header {
		Strict-Transport-Security "max-age=31536000"
		X-Content-Type-Options "nosniff"
		Content-Security-Policy "frame-ancestors 'self'"
		Referrer-Policy "strict-origin-when-cross-origin"
		-Server
	}
}

Caddy setzt HSTS und diese Header nicht von selbst; Sie müssen sie also tatsächlich eintragen. -Server entfernt den Header Server. In Lektion 9.4 setzen Sie in einem gleichartigen Block Ihren eigenen Header X-Weboke-Cursus für die Aufgabe.

In nginx setzen Sie dieselben Zeilen in den server-Block für Port 443:

add_header Strict-Transport-Security "max-age=31536000" always;
add_header X-Content-Type-Options "nosniff" always;
add_header Content-Security-Policy "frame-ancestors 'self'" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;

always sorgt dafür, dass sie auch bei Fehlerseiten mitgesendet werden. Achten Sie auf eine bekannte Falle von nginx: Steht in einem location-Block selbst ein einziges add_header, gelten die add_header-Zeilen des server-Blocks für diese Location nicht mehr. Prüfen Sie deshalb immer das Ergebnis:

anna@laptop:~$ curl -sI https://example.com | grep -iE 'strict|nosniff|frame|referrer'
strict-transport-security: max-age=31536000
x-content-type-options: nosniff
content-security-policy: frame-ancestors 'self'
referrer-policy: strict-origin-when-cross-origin

security.txt: So kann Ihnen jemand eine Sicherheitslücke melden

Angenommen, jemand findet eine Lücke auf Ihrem Server, etwa ein offenes Verzeichnis oder einen veralteten Dienst. Woher weiß diese Person, wen sie warnen soll? Dafür gibt es security.txt (RFC 9116): eine kleine Textdatei an einem festen Ort, https://<jouwdomein>/.well-known/security.txt.

Contact: mailto:security@example.com
Expires: 2027-10-31T23:00:00Z
Preferred-Languages: nl, en
Canonical: https://example.com/.well-known/security.txt

Die Regeln:

  • Contact ist Pflicht: eine mailto:-, https://- oder tel:-Adresse, an die Meldungen gehen. Verwenden Sie eine Adresse, die auch wirklich jemand liest.
  • Expires ist Pflicht und darf nur einmal vorkommen: das Datum, nach dem die Datei als veraltet gilt. Die RFC empfiehlt ein Datum innerhalb eines Jahres. So bleibt keine Datei mit einer längst vergessenen Adresse stehen. Tragen Sie in Ihren Kalender ein, wann Sie sie verlängern müssen.
  • Preferred-Languages, Canonical und Policy (ein Link zu Ihrer Richtlinie für Meldungen) sind optional.
  • Die Datei muss über https ausgeliefert werden, als reiner Text (text/plain, UTF-8). Der alte Ort /security.txt ist zusätzlich erlaubt, aber /.well-known/ hat Vorrang.

Ablegen bei einer statischen Website:

anna@web1:~$ sudo mkdir -p /var/www/example.com/.well-known
anna@web1:~$ sudoedit /var/www/example.com/.well-known/security.txt
anna@laptop:~$ curl -sI https://example.com/.well-known/security.txt | grep -i content-type
content-type: text/plain; charset=utf-8

Verwenden Sie in nginx das Auffangnetz location ~ /\. { deny all; } aus Lektion 7.2, setzen Sie davor eine Ausnahme: location ^~ /.well-known/ { }. Für eine Anwendung hinter einem Reverse Proxy können Sie in Caddy den Pfad /.well-known/security.txt mit einem handle-Block und file_server auf eine Datei zeigen lassen.

Ein häufiger Fehler: Eine Website oder Anwendung beantwortet jeden unbekannten Pfad mit der Startseite und Status 200. Dann "existiert" security.txt zwar, ist aber HTML. Prüfen Sie also auch den Inhalt.

Unter AlmaLinux und Rocky Linux

Caddy kommt dort aus der Quelle der Entwickler oder aus EPEL/COPR. Wie bei nginx muss SELinux einen Reverse Proxy erlauben (setsebool -P httpd_can_network_connect 1). Die Caddyfile und die Header sind identisch.

Zusammenfassung

  • Caddy kümmert sich selbst um Zertifikate, Erneuerung und die Umleitung auf https; reverse_proxy gibt die richtigen Header automatisch weiter.
  • HSTS lässt Browser sich merken, dass Ihre Website nur https ist; bauen Sie max-age schrittweise auf, seien Sie vorsichtig mit includeSubDomains und sehr vorsichtig mit preload.
  • Setzen Sie außerdem X-Content-Type-Options: nosniff, frame-ancestors 'self' und eine Referrer-Policy; in Caddy mit header, in nginx mit add_header ... always, und prüfen Sie mit curl -I.
  • security.txt liegt unter /.well-known/security.txt, über https, als reiner Text, mit dem Pflichtfeld Contact und genau einem Expires innerhalb eines Jahres.

Quiz

1. Warum hilft HSTS, obwohl Sie http bereits auf https umleiten?



2. Sie setzen HSTS mit max-age=31536000; includeSubDomains. Eine Woche später stellt sich heraus, dass camera.example.com kein gültiges Zertifikat hat. Was bemerken Besucher, die Ihre Website schon einmal besucht haben?



3. Welche Felder sind in einer security.txt Pflicht?



4. Sie haben in nginx die Sicherheitsheader in den server-Block gesetzt, aber für /api/ werden sie nicht mitgesendet. Im Block location /api/ steht ein eigenes add_header. Was ist los?



5. Was müssen Sie tun, bevor Sie preload zu Ihrem HSTS-Header hinzufügen?



Aufgabe

Aufgabe Z7.4: HSTS, Header und security.txt. Setzen Sie für Ihre Website HSTS (mindestens 180 Tage, nachdem https eine Zeit lang zuverlässig funktioniert), X-Content-Type-Options: nosniff und frame-ancestors 'self' (oder X-Frame-Options), und veröffentlichen Sie eine security.txt mit Contact und einem Expires innerhalb eines Jahres. Geben Sie Ihren Hostnamen ein. Das Programm ruft https://<hostnaam>/ ab und prüft die Header, ruft https://<hostnaam>/.well-known/security.txt ab und prüft die Felder. Es speichert nichts außer dem Ergebnis und dem Expires-Datum.

Aufgabe Z7.4: HSTS, Header und security.txt

Nur für angemeldete Kursteilnehmer. Wir rufen https://<naam>/ und /.well-known/security.txt ab (nur GET).




Was Sie eingeben und was wir finden, speichern wir nicht. Ihr Browser merkt sich Ihre Antworten und ob Sie die Aufgabe bestanden haben. Sind Sie angemeldet, speichern wir in Meine Kurse nur, dass Sie die Aufgabe (fast) richtig hatten; auch das können Sie dort löschen.

Weiterführende Informationen

Einen Moment bitte…

Richten Sie Ihre Domains ein

Legen Sie für jede Domain die Nameserver, die Verknüpfung mit Ihrem Hosting und den künftigen Inhaber fest.

Ihre Domains werden geladen…