Gå direkte til indholdet

Cookieindstillinger

Vælg for hver type, hvilke cookies du tillader. Du kan altid ændre dit valg via Cookieindstillinger nederst på hver side. Privatlivspolitik

Nødvendige

Altid slået til

Nødvendige for at logge ind, gemme din kurv og huske dine valg. De er altid slået til.

Hvilke cookies?
  • weboke_sessie, weboke_klant, weboke_remember: din session og at forblive logget ind
  • weboke_basket: din kurv
  • wkBtwIncl: vise priser med eller uden moms
  • wok_cookies: dit cookievalg, 12 måneder

Måler, hvilken annonce der fører til et besøg eller en bestilling, så vi ikke betaler for annoncer, der ikke virker.

Hvilke cookies?
  • Google Ads via Google Tag Manager (_gcl_au, _gcl_aw), op til 90 dage
  • OpenAI Ads, annoncer i ChatGPT
  • wok_aff: hvilken partner der henviste dig til os (affiliateprogram), 60 dage

4,6

Land og sprog

Hvert land har sin egen side med landets priser og moms.

Se

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 caddy

Brug 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 -f

I 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=31536000

Browseren 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:

  1. Slå først HSTS til, når https virker overalt, og fornyelsen sker automatisk (lektion 7.3).
  2. Start med en kort max-age, for eksempel en dag (86400), og øg trinvist op til et år.
  3. 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.
  4. preload anmoder om optagelse på en liste, der er indbygget i browserne (hstspreload.org). Det kræver blandt andet en max-age på mindst et år, includeSubDomains og 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:

HeaderBeskytter modVærdi at starte med
X-Content-Type-Optionsbrowseren gætter, hvad en fil er, så et uploadet "billede" kan køre som scriptnosniff
Content-Security-Policy: frame-ancestors (eller den ældre X-Frame-Options)clickjacking: et andet site indlæser din side usynligt i en frameframe-ancestors 'self' (eller X-Frame-Options: SAMEORIGIN)
Referrer-Policyadressen på din side (med søgeord eller ordrenumre) lækker til andre sitesstrict-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-origin

security.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.txt

Reglerne:

  • Contact er obligatorisk: en mailto:-, https://- eller tel:-adresse, hvor meldingerne lander. Brug en adresse, som nogen faktisk læser.
  • Expires er 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, Canonical og Policy (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.txt må 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-8

Bruger 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_proxy sender automatisk de rigtige headers videre.
  • HSTS får browsere til at huske, at dit site kun er https; byg max-age op gradvist, vær forsigtig med includeSubDomains og meget forsigtig med preload.
  • Sæt desuden X-Content-Type-Options: nosniff, frame-ancestors 'self' og en Referrer-Policy; i Caddy med header, i nginx med add_header ... always, og kontrollér med curl -I.
  • security.txt ligger på /.well-known/security.txt, via https, som ren tekst, med obligatorisk Contact og én Expires inden for et år.

Quiz

1. Hvorfor hjælper HSTS, når du allerede omdirigerer http til https?



2. Du sætter HSTS med max-age=31536000; includeSubDomains. En uge senere viser det sig, at camera.example.com ikke har et gyldigt certifikat. Hvad oplever besøgende, der tidligere har besøgt dit site?



3. Hvilke felter er obligatoriske i en security.txt?



4. Du har i nginx sat sikkerhedsheaderne i server-blokken, men for /api/ kommer de ikke med. I blokken location /api/ står der én egen add_header. Hvad er der galt?



5. Hvad skal du gøre, før du tilføjer preload til din HSTS-header?



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.

Opgave Z7.4: HSTS, headers og security.txt

Kun for tilmeldte kursister. Vi henter https://<naam>/ og /.well-known/security.txt (kun GET).




Det, du udfylder, og hvad vi finder, gemmer vi ikke. Din browser husker dine svar, og om du har bestået opgaven. Er du logget ind, gemmer vi kun, at du (næsten) bestod opgaven, i Mine kurser; der kan du også slette det.

Læs mere

Et øjeblik…

Opsæt dine domæner

Angiv for hvert domæne navneserverne, tilknytningen til din hosting, og hvem der bliver ejer.

Indlæser dine domæner…