Modul 7 · 7.4
Caddy, HSTS og security.txt
Modul 7: Domæne, webserver og https · Læsetid: 12 minutter
Læringsmål: Efter denne lektion kan du bruge Caddy som en enkel webserver med automatisk https, sætte HSTS og de vigtigste sikkerhedsheaders (i Caddy og nginx) uden at gøre dit site utilgængeligt og udgive en gyldig security.txt.
Centrale begreber: Caddy, Caddyfile, automatisk 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 uden bekymringer
I lektion 7.2 og 7.3 byggede du et site med https ved hjælp af nginx og certbot. Det er to programmer, et par filer og en timer. Caddy klarer det hele i ét: Det er en webserver med en indbygget ACME-klient. Står et navn i konfigurationen, peger det på serveren, og er port 80 og 443 tilgængelige, så henter Caddy selv et certifikat, fornyer det i god tid og omdirigerer http til https.
Caddy findes i pakkekilden til Debian og Ubuntu (en lidt ældre version). Udviklerne tilbyder også deres egen apt-kilde med den nyeste version, med egen nøgle og Signed-By som i lektion 4.1. I modul 9 kører Caddy som container foran dine Docker-tjenester (lektion 9.4). Her bruger du den som en almindelig tjeneste.
anna@web1:~$ sudo apt install caddy
anna@web1:~$ systemctl status caddyBrug enten nginx eller Caddy på port 80 og 443, ikke begge: Kun ét program kan lytte på en port.
Caddyfile
Konfigurationen ligger i /etc/caddy/Caddyfile. Et statisk site og en applikation bag en 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
}Det er det hele. Caddy lytter automatisk på IPv4 og IPv6, anmoder om certifikater til de tre navne, omdirigerer http til https og sender ved reverse_proxy automatisk headerne X-Forwarded-For og X-Forwarded-Proto videre (det, du gjorde i hånden i nginx, lektion 7.2).
Test og genindlæsning foregår som med nginx:
anna@web1:~$ caddy validate --config /etc/caddy/Caddyfile
Valid configuration
anna@web1:~$ sudo systemctl reload caddy
anna@web1:~$ sudo journalctl -u caddy -fI journalen kan du se, at certifikaterne bliver hentet. Går det galt, står årsagen der: som regel den samme som med certbot (port 80 lukket, navnet peger et andet sted hen, IPv6 virker ikke; lektion 7.3).
HSTS: lad browseren huske, at det er https
Omdirigering fra http til https har ét svagt punkt: Den allerførste forespørgsel via http sendes stadig ukrypteret. En person på samme netværk kan opsnappe den og holde den besøgende på http. HSTS (HTTP Strict Transport Security, RFC 6797) løser det. Dit site sender denne header med via https:
Strict-Transport-Security: max-age=31536000Browseren husker så i et år (31.536.000 sekunder), at dette navn kun må bruges via https. Skriver den besøgende senere http://, laver browseren det selv om til https, før noget overhovedet sendes over netværket. En HSTS-header, der kommer ind via http, ignorerer browseren; den tæller kun via https.
Der er en bagside. Har en browser husket HSTS og ser den en certifikatfejl (udløbet, forkert navn), får den besøgende ingen knap til at fortsætte alligevel. Dit site er så utilgængeligt for de besøgende, indtil certifikatet er i orden. Derfor:
- Slå først HSTS til, når https virker overalt, og fornyelsen sker automatisk (lektion 7.3).
- Start med en kort
max-age, for eksempel en dag (86400), og øg trinvist op til et år. - Vær forsigtig med
includeSubDomains: Det gælder for alle subdomæner, også et gammelt subdomæne med en enhed eller tjeneste uden gyldigt certifikat. preloadanmoder om optagelse på en liste, der er indbygget i browserne (hstspreload.org). Det kræver blandt andet enmax-agepå mindst et år,includeSubDomainsog https på alle subdomæner. Det tager måneder at blive fjernet igen. Gør det kun, hvis du er sikker på, at hele domænet er https for altid.
De andre sikkerhedsheaders
Ud over HSTS er der et par headers, der hjælper meget for lidt arbejde:
| Header | Beskytter mod | Værdi at starte med |
|---|---|---|
X-Content-Type-Options | browseren gætter, hvad en fil er, så et uploadet "billede" kan køre som script | nosniff |
Content-Security-Policy: frame-ancestors (eller den ældre X-Frame-Options) | clickjacking: et andet site indlæser din side usynligt i en frame | frame-ancestors 'self' (eller X-Frame-Options: SAMEORIGIN) |
Referrer-Policy | adressen på din side (med søgeord eller ordrenumre) lækker til andre sites | strict-origin-when-cross-origin |
En komplet Content-Security-Policy (hvilke scripts og styles der må indlæses) skal skræddersys til hvert site og ligger uden for dette kursus; start kun med frame-ancestors.
I Caddy sætter du dem med header-direktivet i blokken for et site:
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 sætter ikke selv HSTS og disse headers; du skal altså selv skrive dem ind. -Server fjerner headeren Server. I lektion 9.4 sætter du i samme slags blok din egen header X-Weboke-Cursus til opgaven.
I nginx sætter du de samme linjer i server-blokken for 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 sørger for, at de også sendes med på fejlsider. Pas på en kendt faldgrube i nginx: Står der i en location-blok selv én add_header, så gælder add_header-linjerne fra server-blokken ikke længere for den location. Kontrollér derfor altid resultatet:
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-originsecurity.txt: så kan andre melde et sikkerhedshul til dig
Forestil dig, at nogen finder et sikkerhedshul på din server, for eksempel en åben mappe eller en forældet tjeneste. Hvordan ved personen, hvem der skal advares? Det er det, security.txt (RFC 9116) er til: en lille tekstfil på et fast sted, 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.txtReglerne:
Contacter obligatorisk: enmailto:-,https://- ellertel:-adresse, hvor meldingerne lander. Brug en adresse, som nogen faktisk læser.Expireser obligatorisk og må kun forekomme én gang: datoen, hvorefter filen regnes for forældet. RFC'en anbefaler en dato inden for et år. Så bliver der ikke liggende en fil med en for længst glemt adresse. Skriv i din kalender, hvornår du skal forlænge den.Preferred-Languages,CanonicalogPolicy(et link til din politik for meldinger) er valgfrie.- Filen skal leveres via https som ren tekst (
text/plain, UTF-8). Det gamle sted/security.txtmå bruges som ekstra, men/.well-known/har forrang.
Sådan lægger du den på et statisk site:
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-8Bruger du i nginx sikkerhedsnettet location ~ /\. { deny all; } fra lektion 7.2, så sæt en undtagelse foran: location ^~ /.well-known/ { }. For en applikation bag en reverse proxy kan du i Caddy lade stien /.well-known/security.txt pege på en fil med en handle-blok og file_server.
En almindelig fejl: et site eller en applikation, der besvarer enhver ukendt sti med forsiden og status 200. Så "findes" security.txt, men det er HTML. Kontrollér derfor også indholdet.
På AlmaLinux og Rocky Linux
Her kommer Caddy fra udviklernes egen kilde eller fra EPEL/COPR. Ligesom med nginx skal SELinux tillade en reverse proxy (setsebool -P httpd_can_network_connect 1). Caddyfile og headers er de samme.
Opsummering
- Caddy klarer selv certifikater, fornyelse og omdirigering til https;
reverse_proxysender automatisk de rigtige headers videre. - HSTS får browsere til at huske, at dit site kun er https; byg
max-ageop gradvist, vær forsigtig medincludeSubDomainsog meget forsigtig medpreload. - Sæt desuden
X-Content-Type-Options: nosniff,frame-ancestors 'self'og enReferrer-Policy; i Caddy medheader, i nginx medadd_header ... always, og kontrollér medcurl -I. - security.txt ligger på
/.well-known/security.txt, via https, som ren tekst, med obligatoriskContactog énExpiresinden for et år.
Quiz
Opgave
Opgave Z7.4: HSTS, headers og security.txt. Sæt HSTS for dit site (mindst 180 dage, efter at https har virket godt et stykke tid), X-Content-Type-Options: nosniff og frame-ancestors 'self' (eller X-Frame-Options), og udgiv en security.txt med Contact og en Expires inden for et år. Udfyld dit hostnavn. Programmet henter https://<hostnaam>/ og kontrollerer headerne, og henter https://<hostnaam>/.well-known/security.txt og kontrollerer felterne. Det gemmer intet ud over resultatet og Expires-datoen.
Læs mere
- HSTS og sikkerhedsheaders til din hjemmeside
- Caddy, Automatic HTTPS: https://caddyserver.com/docs/automatic-https
- Caddy, header-direktivet: https://caddyserver.com/docs/caddyfile/directives/header
- RFC 6797, HTTP Strict Transport Security: https://www.rfc-editor.org/rfc/rfc6797.html
- HSTS-preload-listen og kravene: https://hstspreload.org/
- RFC 9116, security.txt: https://www.rfc-editor.org/rfc/rfc9116.html
- securitytxt.org (opret og kontrollér): https://securitytxt.org/
- Sådan lægger du en security.txt på din hjemmeside
- VPS: fra første login til sikker server 5.1: Caddy: en hjemmeside med automatisk https
