Eine kleine Website absichern: Cloudflare, DNS, Mail und der Dev-Server
Wie dieses Portfolio abgesichert ist, Schicht für Schicht: Security-Header, Cloudflare-Einstellungen, DNSSEC, CAA, SPF, DKIM und DMARC und ein Dev-Server ohne offene Ports.
KI-Zusammenfassung anfordern
Diese Website ist statisch. Es gibt keine Datenbank, keinen Login und keinen Servercode, in den jemand einbrechen könnte. Was die Seite selbst angeht, ist sie damit von Haus aus sicher. Aufmerksamkeit braucht alles drumherum: die Domain, die DNS-Einträge, die E-Mail auf derselben Domain und der Rechner, von dem aus ich deploye.
Hier steht, wie jede dieser Schichten eingerichtet ist und was ich für jede kleine Website empfehle.
1. Die Seite: Header, die die Hauptarbeit machen
Die Seite ist mit Astro gebaut und wird von Cloudflare als statische Dateien ausgeliefert. Jede Antwort trägt eine Reihe von Security-Headern, festgelegt in einer einzigen _headers-Datei. Die wichtigsten, gekürzt:
Content-Security-Policy: default-src 'self'; script-src 'self' 'sha256-…'; style-src 'self' 'sha256-…'; frame-ancestors 'none'; object-src 'none'; base-uri 'self'
Strict-Transport-Security: max-age=63072000; includeSubDomains
X-Content-Type-Options: nosniff
Referrer-Policy: strict-origin-when-cross-origin
Permissions-Policy: geolocation=(), camera=(), microphone=()
Der wichtigste Teil ist die Content Security Policy. Statt der üblichen Abkürzung 'unsafe-inline' hasht ein kleiner Build-Schritt jedes Inline-Script und jeden Inline-Style und schreibt die Hashes in die Policy. Schafft es jemand, ein Script in eine Seite einzuschleusen, führt der Browser es nicht aus. Derselbe Build-Schritt bricht ab, sobald eine Seite style=""-Attribute oder onclick=""-Handler enthält. So kann die Policy nicht aus Versehen aufgeweicht werden.
2. Cloudflare: nur HTTPS, nur modernes TLS
Zwei Einstellungen in Cloudflare ergänzen, was die Header anfangen:
- Always Use HTTPS leitet jede
http://-Anfrage aufhttps://um. HSTS allein deckt den allerersten Besuch über HTTP nicht ab, weil Browser es dort ignorieren. Die Umleitung schließt diese Lücke. - Minimale TLS-Version 1.2 weist alte und schwache Protokollversionen ab.
Der eigene HSTS-Schalter von Cloudflare bleibt aus, weil die Seite den Header schon selbst sendet. Zwei Quellen für denselben Header sorgen nur für Verwirrung.
3. Domain und DNS: DNSSEC, CAA und Zertifikats-Alarme
DNSSEC signiert die DNS-Antworten, damit niemand deinen Besuchern eine gefälschte IP-Adresse unterjubeln kann. Cloudflare übernimmt das Signieren, sobald es eingeschaltet ist. Die zweite Hälfte passiert beim Registrar, und bei .de-Domains gibt es einen Haken: Die Registry erwartet den DNSKEY, nicht den DS-Eintrag, den Cloudflare zuerst anzeigt. Im Formular des Registrars heißt das: Häkchen bei „automatischer Modus“ entfernen (der funktioniert nur mit den eigenen Nameservern des Registrars) und den Schlüssel einfügen. Ein paar Minuten später validieren die öffentlichen Resolver die Domain.
Eine Regel zum Merken: Bevor du die Domain jemals auf andere Nameserver umziehst, entferne zuerst den Schlüssel beim Registrar. Sonst ist die Domain für alle, die DNSSEC prüfen, nicht mehr erreichbar.
CAA-Einträge legen fest, welche Zertifizierungsstellen Zertifikate für die Domain ausstellen dürfen. Alle anderen müssen ablehnen. Cloudflare ergänzt die Stellen, die es selbst nutzt, automatisch, damit die Liste vollständig bleibt.
Certificate Transparency Monitoring schickt eine Mail, sobald irgendeine Zertifizierungsstelle ein Zertifikat für die Domain ausstellt. Würde jemand die Domain übernehmen, würde ich es so merken. Der Alarm geht an eine Adresse außerhalb der Domain, denn während einer Übernahme kommt Mail an die eigene Domain womöglich nicht mehr an.
Das ist auch das eigentliche Risiko: nicht ein Hack beim Registrar selbst, sondern dass jemand in das Konto dort kommt. Also: Zwei-Faktor-Authentifizierung, ein eigenes Passwort und eine Wiederherstellungs-Mail, die nicht an der Domain hängt. DNSSEC hilft dagegen nicht, denn wer das Konto kontrolliert, kann auch den Schlüssel ändern.
4. Mail: SPF, DKIM und DMARC
Auf derselben Domain läuft auch die Mail, also braucht es die üblichen drei Einträge:
- SPF sagt, welche Server Mail für die Domain verschicken dürfen.
- DKIM signiert jede ausgehende Mail, damit Empfänger erkennen, dass sie wirklich von dir kommt.
- DMARC sagt empfangenden Servern, was sie mit Mails tun sollen, die diese Prüfungen nicht bestehen.
Eine typische Falle mit Cloudflare: Der DKIM-Eintrag ist meist ein CNAME, der auf den Mail-Anbieter zeigt. Läuft er über den Cloudflare-Proxy (die orange Wolke), antwortet Cloudflare mit seinen eigenen IP-Adressen, statt den Schlüssel des Anbieters weiterzugeben, und jede Mail geht unsigniert raus. Deshalb: Mail-Einträge bekommen nie die orange Wolke, immer DNS only.
Zum Prüfen schickst du dir eine Testmail und schaust in die Header. Dort sollte dkim=pass, spf=pass und dmarc=pass stehen.
DMARC führst du am besten in Stufen ein: Starte mit p=none und lies ein, zwei Wochen lang die Berichte. Fällt nichts Legitimes durch, wechselst du auf p=quarantine und später auf p=reject. Dann landen Mails, die nur so tun, als kämen sie von deiner Domain, im Spam oder werden abgewiesen. Etwa eine gefälschte Rechnung an einen Kunden.
5. Der Dev-Server: gar keine offenen Ports
Ich arbeite auch von einem kleinen VPS aus. Er hostet keine Websites und muss deshalb aus dem Internet überhaupt nicht erreichbar sein:
- Die Firewall lässt nur Verkehr über das private Netz (Tailscale) durch, und die Firewall des Anbieters hat keine eingehenden Regeln.
- SSH lauscht nur auf der Adresse im privaten Netz, akzeptiert nur Schlüssel und lässt keinen Root-Login zu.
- X11- und TCP-Forwarding sind aus, damit ein gestohlener Login nicht zum Tunnel wird.
- Sicherheitsupdates installieren sich selbst.
- Auf der Tailscale-Seite verlangt SSH regelmäßig eine frische Bestätigung des Logins, und Root-Logins sind nicht erlaubt.
- Im privaten Netz bleiben nur Geräte, die wirklich genutzt werden, denn jedes Gerät darin kann den Server erreichen.
6. GitHub und CI: kleine Schlüssel
Der Server spricht mit GitHub über ein Fine-grained Token, das nur das eine Repository erreicht, an dem ich dort arbeite, statt über ein breites Token mit Zugriff auf alles. Landet ein Token jemals dort, wo es nicht hingehört, etwa in einem Chat oder Log, gilt es als geleakt: sofort neu erzeugen.
Die CI-Pipeline folgt demselben Gedanken: GitHub Actions sind auf exakte Commits festgenagelt, damit ein verschobener Tag den Code nicht austauschen kann. Das Token des Workflows darf nur lesen, und Dependabot schlägt jede Woche Updates vor.
Die Kurzfassung
- Seite: strenge CSP mit Hashes, HSTS, keine Inline-Styles oder Event-Handler.
- Cloudflare: Always Use HTTPS, mindestens TLS 1.2.
- Domain: DNSSEC, CAA, Zertifikats-Alarme, 2FA beim Registrar.
- Mail: SPF, DKIM (DNS only!), DMARC in Stufen eingeführt, beginnend mit
none. - Server: keine offenen Ports, SSH nur über ein privates Netz, nur Schlüssel.
- Zugänge: Tokens so eng wie möglich, und sofort neu erzeugen, falls eins leakt.
Jede dieser Schichten schließt eine andere Lücke, und richtig schützen sie nur zusammen. Jedes Setup ist anders: anderes Hosting, ein anderer Mail-Anbieter, ein anderer Registrar und andere Leute, die Zugriff brauchen. Wenn ich deine Website genauso prüfen und absichern soll, melde dich.
