Modul 7 · 7.4
Caddy, HSTS och security.txt
Modul 7: Domän, webbserver och https · Lästid: 12 minuter
Lärandemål: Efter den här lektionen kan du använda Caddy som en enkel webbserver med automatisk https, slå på HSTS och de viktigaste säkerhetsheadersen (i Caddy och nginx) utan att göra din webbplats onåbar, och publicera en giltig security.txt.
Nyckelbegrepp: 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 utan att du behöver tänka på det
I lektion 7.2 och 7.3 byggde du en webbplats med https med hjälp av nginx och certbot. Det är två program, några filer och en timer. Caddy gör allt i ett: det är en webbserver med en inbyggd ACME-klient. Om ett namn finns i konfigurationen, pekar på servern och port 80 och 443 går att nå, hämtar Caddy själv ett certifikat, förnyar det i tid och skickar vidare http till https.
Caddy finns i paketkällan för Debian och Ubuntu (en något äldre version). Utvecklarna erbjuder också en egen apt-källa med den senaste versionen, med en egen nyckel och Signed-By som i lektion 4.1. I modul 9 kör du Caddy som container för dina Docker-tjänster (lektion 9.4). Här använder du det som en vanlig tjänst.
anna@web1:~$ sudo apt install caddy
anna@web1:~$ systemctl status caddyAnvänd antingen nginx eller Caddy på port 80 och 443, inte båda: bara ett program kan lyssna på en port.
Caddyfilen
Konfigurationen finns i /etc/caddy/Caddyfile. En statisk webbplats och en applikation bakom en omvänd 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 är allt. Caddy lyssnar automatiskt på IPv4 och IPv6, begär certifikat för de tre namnen, skickar vidare http till https och skickar vid reverse_proxy automatiskt med headerraderna X-Forwarded-For och X-Forwarded-Proto (det du gjorde för hand i nginx, lektion 7.2).
Testa och ladda om på samma sätt 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 ser du hur certifikaten hämtas. Om något går fel står orsaken där: oftast samma som med certbot (port 80 stängd, namnet pekar någon annanstans, IPv6 fungerar inte; lektion 7.3).
HSTS: låt webbläsaren komma ihåg att det är https
Att skicka vidare http till https har en svag punkt: den allra första förfrågan via http går fortfarande okrypterad. Någon på samma nätverk kan fånga upp den och hålla kvar besökaren på http. HSTS (HTTP Strict Transport Security, RFC 6797) löser det. Din webbplats skickar med den här headerraden via https:
Strict-Transport-Security: max-age=31536000Webbläsaren kommer då ihåg i ett år (31.536.000 sekunder) att det här namnet bara får användas via https. Om besökaren senare skriver http:// gör webbläsaren själv om det till https, innan något skickas över nätverket. En HSTS-header som kommer in via http ignoreras av webbläsaren; den gäller bara via https.
Det finns en baksida. Om en webbläsare har sparat HSTS och ser ett certifikatfel (utgånget, fel namn) får besökaren ingen knapp för att fortsätta ändå. Din webbplats är då onåbar för de besökarna tills certifikatet stämmer. Därför:
- Slå på HSTS först när https fungerar överallt och förnyelsen sker automatiskt (lektion 7.3).
- Börja med en kort
max-age, till exempel en dag (86400), och öka stegvis till ett år. - Var försiktig med
includeSubDomains: det gäller för varje underdomän, även en gammal underdomän med en enhet eller tjänst utan giltigt certifikat. preloadbegär att domänen tas med i en lista som är inbyggd i webbläsare (hstspreload.org). Där krävs bland annat enmax-agepå minst ett år,includeSubDomainsoch https på alla underdomäner. Att komma bort från listan tar månader. Gör det bara om du är säker på att hela domänen är https för gott.
De andra säkerhetsheadersen
Förutom HSTS finns det några headerrader som hjälper mycket med liten insats:
| Headerrad | Skyddar mot | Värde att börja med |
|---|---|---|
X-Content-Type-Options | webbläsaren gissar vad en fil är, så att en uppladdad "bild" kan köras som skript | nosniff |
Content-Security-Policy: frame-ancestors (eller den äldre X-Frame-Options) | clickjacking: en annan webbplats laddar din sida osynligt i en ram | frame-ancestors 'self' (eller X-Frame-Options: SAMEORIGIN) |
Referrer-Policy | adressen till din sida (med sökord eller ordernummer) läcker till andra webbplatser | strict-origin-when-cross-origin |
En fullständig Content-Security-Policy (vilka skript och stilmallar som får laddas) måste anpassas för varje webbplats och ingår inte i den här kursen; börja med bara frame-ancestors.
I Caddy sätter du dem med header-direktivet i blocket för en webbplats:
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 inte HSTS och de här headerraderna själv, så du måste verkligen lägga in dem. -Server tar bort headerraden Server. I lektion 9.4 lägger du i samma sorts block in din egen headerrad X-Weboke-Cursus för uppgiften.
I nginx lägger du samma rader i server-blocket 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 gör att de skickas med även på felsidor. Se upp för en känd fälla i nginx: om ett location-block själv innehåller en enda add_header, gäller inte längre add_header-raderna från server-blocket för den location. Kontrollera därför alltid 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 någon rapportera en sårbarhet till dig
Anta att någon hittar en sårbarhet på din server, till exempel en öppen katalog eller en föråldrad tjänst. Hur vet den personen vem som ska varnas? Det är vad security.txt (RFC 9116) är till för: en liten textfil på en fast plats, 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.txtReglerna:
Contactär obligatoriskt: enmailto:-,https://- ellertel:-adress dit rapporterna går. Använd en adress som någon faktiskt läser.Expiresär obligatoriskt och får bara förekomma en gång: datumet då filen räknas som föråldrad. RFC:n rekommenderar ett datum inom ett år. På så vis blir det inte kvar en fil med en sedan länge bortglömd adress. Skriv in i din kalender när du behöver förlänga den.Preferred-Languages,CanonicalochPolicy(en länk till din policy för rapporter) är valfria.- Filen måste levereras via https, som ren text (
text/plain, UTF-8). Den gamla platsen/security.txtfår användas som komplement, men/.well-known/har företräde.
Så lägger du den på plats för en statisk webbplats:
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-8Om du i nginx använder skyddsnätet location ~ /\. { deny all; } från lektion 7.2, lägg då ett undantag före det: location ^~ /.well-known/ { }. För en applikation bakom en omvänd proxy kan du i Caddy låta sökvägen /.well-known/security.txt peka på en fil med ett handle-block och file_server.
Ett vanligt misstag: en webbplats eller applikation som svarar på varje okänd sökväg med startsidan och status 200. Då "finns" security.txt, men den är HTML. Kontrollera därför även innehållet.
På AlmaLinux och Rocky Linux
Där hämtar du Caddy från utvecklarnas källa eller från EPEL/COPR. Precis som med nginx måste SELinux tillåta en omvänd proxy (setsebool -P httpd_can_network_connect 1). Caddyfilen och headersen är desamma.
Sammanfattning
- Caddy sköter certifikat, förnyelse och vidarebefordran till https själv;
reverse_proxyskickar automatiskt med rätt headerrader. - HSTS låter webbläsare komma ihåg att din webbplats bara är https; bygg upp
max-agestegvis, var försiktig medincludeSubDomainsoch mycket försiktig medpreload. - Sätt dessutom
X-Content-Type-Options: nosniff,frame-ancestors 'self'och enReferrer-Policy; i Caddy medheader, i nginx medadd_header ... always, och kontrollera medcurl -I. - security.txt ligger på
/.well-known/security.txt, via https, som ren text, med obligatorisktContactoch en endaExpiresinom ett år.
Quiz
Uppgift
Uppgift Z7.4: HSTS, headers och security.txt. Slå på HSTS för din webbplats (minst 180 dagar, efter att https har fungerat bra ett tag), X-Content-Type-Options: nosniff och frame-ancestors 'self' (eller X-Frame-Options), och publicera en security.txt med Contact och en Expires inom ett år. Fyll i ditt värdnamn. Programmet hämtar https://<hostnaam>/ och kontrollerar headerraderna, och hämtar https://<hostnaam>/.well-known/security.txt och kontrollerar fälten. Det sparar inget annat än resultatet och Expires-datumet.
Läs mer
- HSTS och säkerhetsheaders för din webbplats
- 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-listan och kraven: https://hstspreload.org/
- RFC 9116, security.txt: https://www.rfc-editor.org/rfc/rfc9116.html
- securitytxt.org (skapa och kontrollera): https://securitytxt.org/
- Lägg upp en security.txt på din webbplats
- VPS: från första inloggningen till en säker server 5.1: Caddy: en webbplats med automatisk https
