9 min lezen

Security headers instellen: van melding naar werkende configuratie

Veel website-scans melden dat er security headers ontbreken, maar laten je vervolgens in het ongewisse over wat je precies moet doen. Dit artikel legt de zes belangrijkste headers uit, wat ze beschermen en hoe je ze toevoegt in nginx en in Apache via .htaccess. Het is geschreven voor mkb-ondernemers die hun eigen site beheren en voor bureaus die meerdere klantsites netjes willen opleveren. Je krijgt concrete, kant-en-klare configuratie die je kunt aanpassen aan je eigen situatie. Het doel is dat je na het lezen niet alleen begrijpt wat de melding betekent, maar de waarschuwing ook daadwerkelijk kunt wegwerken.

Wat security headers zijn en waarom ze ertoe doen

Security headers zijn extra regels die je webserver meestuurt bovenop de gewone inhoud van een pagina. Ze staan in de HTTP-respons, het stukje technische informatie dat de browser ontvangt voordat hij de eigenlijke pagina laat zien. In die respons kan je server instructies plaatsen zoals: gebruik altijd een beveiligde verbinding, sta niet toe dat deze pagina in een frame van een andere site wordt geladen, of laad alleen scripts van vertrouwde bronnen. De browser leest die instructies en handelt ernaar. Voor de bezoeker is daar niets van te merken, en toch verklein je er een flink aantal aanvalsmogelijkheden mee.

Het aantrekkelijke aan headers is dat ze geen wijziging aan je broncode of CMS vereisen. Je past de configuratie van de webserver aan, of een klein bestand zoals .htaccess, en de bescherming geldt meteen voor alle pagina's. Daardoor zijn ze een van de meest kosteneffectieve beveiligingsmaatregelen die er bestaan: relatief weinig werk, brede dekking.

Tegelijk is het geen wondermiddel. Headers beschermen vooral tegen aanvallen die zich in de browser van de bezoeker afspelen, zoals clickjacking en bepaalde vormen van code-injectie. Ze vervangen geen goede invoervalidatie, geen up-to-date software en geen sterke wachtwoorden. Zie ze als een laag in een groter geheel, een laag die vaak ontbreekt en relatief eenvoudig is recht te zetten.

De zes headers die je echt moet kennen

Strict-Transport-Security (HSTS) dwingt af dat browsers je site alleen nog via HTTPS benaderen. Heeft een bezoeker je site eenmaal veilig bezocht, dan weigert de browser daarna elke onbeveiligde verbinding, ook als iemand op een onveilig netwerk probeert in te grijpen. Een veelgebruikte waarde is max-age=31536000 (een jaar), eventueel met includeSubDomains. Zet HSTS pas aan als HTTPS overal werkt, anders sluit je bezoekers tijdelijk buiten.

Content-Security-Policy (CSP) is de krachtigste en tegelijk lastigste header. Hij bepaalt welke bronnen (scripts, stylesheets, afbeeldingen, fonts) de browser mag laden. Een goed ingestelde CSP maakt het voor een aanvaller veel moeilijker om kwaadaardige scripts uit te voeren, de kern van cross-site scripting. Een minimale, voorzichtige start is bijvoorbeeld default-src 'self', waarna je per type bron de toegestane domeinen toevoegt. CSP vraagt testen, want te streng en je eigen scripts werken niet meer.

De overige vier zijn eenvoudiger. X-Frame-Options met de waarde SAMEORIGIN voorkomt dat je site in een frame van een vreemde site wordt geladen (clickjacking). X-Content-Type-Options met nosniff zorgt dat de browser bestandstypen niet zelf gaat raden, wat misbruik voorkomt. Referrer-Policy, bijvoorbeeld strict-origin-when-cross-origin, beperkt hoeveel informatie over de herkomst-URL wordt meegestuurd naar andere sites. Permissions-Policy ten slotte schakelt browserfuncties uit die je niet gebruikt, zoals camera, microfoon of locatie, met een waarde als geolocation=(), camera=(), microphone=().

De headers toevoegen in nginx

In nginx voeg je headers toe met de add_header-instructie, doorgaans binnen het server-blok van je site (vaak een bestand in /etc/nginx/sites-available/ of /etc/nginx/conf.d/). Plaats je de regels in het server-blok, dan gelden ze voor alle locaties van die site. Een werkbare set ziet er zo uit:

add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always; add_header X-Frame-Options "SAMEORIGIN" always; add_header X-Content-Type-Options "nosniff" always; add_header Referrer-Policy "strict-origin-when-cross-origin" always; add_header Permissions-Policy "geolocation=(), camera=(), microphone=()" always; add_header Content-Security-Policy "default-src 'self'; img-src 'self' data:; style-src 'self' 'unsafe-inline'" always;

Let op het sleutelwoord always aan het eind. Zonder dat woord stuurt nginx de header niet mee bij foutpagina's zoals een 404 of 500, terwijl je juist wilt dat de bescherming overal geldt. Een tweede valkuil is dat een add_header in een dieper liggend blok (bijvoorbeeld in een specifieke location) alle add_header-regels uit het bovenliggende blok overschrijft. Definieer je headers dus op een consistent niveau, of herhaal ze waar nodig.

Na het aanpassen test je de configuratie met nginx -t en herlaad je met systemctl reload nginx of nginx -s reload. De test voorkomt dat een typefout je hele server platlegt. Wijzig vervolgens de CSP stap voor stap: begin ruim, kijk in de console van de browser welke bronnen worden geblokkeerd, en versmal de policy tot hij precies past bij wat je site nodig heeft.

De headers toevoegen in Apache en .htaccess

In Apache gebruik je de module mod_headers. Op de meeste gedeelde hostingpakketten staat die al aan, en kun je de headers eenvoudig in een .htaccess-bestand in de hoofdmap van je site zetten. Op een eigen server activeer je de module zo nodig met a2enmod headers. De syntax verschilt van nginx en gebruikt het commando Header set:

<IfModule mod_headers.c> Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains" Header always set X-Frame-Options "SAMEORIGIN" Header always set X-Content-Type-Options "nosniff" Header always set Referrer-Policy "strict-origin-when-cross-origin" Header always set Permissions-Policy "geolocation=(), camera=(), microphone=()" Header always set Content-Security-Policy "default-src 'self'; img-src 'self' data:; style-src 'self' 'unsafe-inline'" </IfModule>

Het codeblok IfModule zorgt dat je site niet stukloopt op servers waar mod_headers ontbreekt. Het woord always na Header werkt vergelijkbaar met nginx: de header wordt dan ook bij foutpagina's meegestuurd. Een .htaccess-bestand werkt direct na opslaan, je hoeft niets te herstarten, wat handig is bij gedeelde hosting waar je geen toegang tot de servervoorkeuren hebt.

Wees voorzichtig met dubbel ingestelde headers. Als je CMS (denk aan een WordPress-plug-in of een securitypakket) zelf al headers stuurt en je voegt ze ook in .htaccess toe, kun je dezelfde header twee keer meekrijgen. Sommige browsers behandelen dat onvoorspelbaar. Controleer daarom altijd het eindresultaat in plaats van alleen aan te nemen dat je configuratie het laatste woord heeft.

Van melding naar gecontroleerde configuratie

Het lastige aan headers is niet ze aanzetten, maar ze juist instellen zonder je eigen site te breken. Een te strenge Content-Security-Policy blokkeert zomaar je Google Analytics, een ingesloten YouTube-video of een betaalwidget. Daarom werk je het beste in kleine stappen: voeg eerst de eenvoudige headers toe (X-Frame-Options, X-Content-Type-Options, Referrer-Policy, Permissions-Policy), controleer dat alles nog werkt, en pak CSP en HSTS daarna apart aan met extra aandacht.

Na elke wijziging wil je weten of de header daadwerkelijk wordt meegestuurd en de juiste waarde heeft. Hiervoor draai je opnieuw een scan. De fix-generators van CheckBorg (beschikbaar in het Pro-pakket) genereren op basis van je scan een kant-en-klaar configuratieblok voor zowel nginx als Apache, dat je kunt kopiëren en plakken. Zo voorkom je tikfouten in de exacte waarden en hoef je de syntax niet uit je hoofd te kennen. Je behoudt de regie, want je plaatst de configuratie zelf en kunt hem aanpassen voordat je live gaat.

Voor bureaus die meerdere sites beheren is het verstandig om een vaste, geteste basisset headers vast te leggen en die als standaard bij elke oplevering te gebruiken. Eén keer goed nadenken, daarna consequent toepassen, scheelt later veel losse meldingen. Hertest periodiek, want een migratie naar een nieuwe server of een CMS-update kan je zorgvuldig ingestelde headers ongemerkt weer wissen.

Praktische checklist

Controleer eerst of je site volledig op HTTPS draait, want HSTS aanzetten zonder werkend HTTPS sluit bezoekers buiten.

Voeg de vier eenvoudige headers toe: X-Frame-Options (SAMEORIGIN), X-Content-Type-Options (nosniff), Referrer-Policy en Permissions-Policy.

Plaats de regels op het juiste niveau: in nginx in het server-blok met always, in Apache in .htaccess binnen een IfModule mod_headers-blok.

Test in nginx met nginx -t en herlaad daarna; in Apache via .htaccess werkt de wijziging direct na opslaan.

Stel Content-Security-Policy ruim in (begin met default-src 'self') en versmal hem stap voor stap aan de hand van de browserconsole.

Zet HSTS pas aan als HTTPS overal stabiel werkt, met bijvoorbeeld max-age=31536000 en includeSubDomains.

Draai een nieuwe scan om te controleren of elke header echt wordt meegestuurd met de juiste waarde, en hertest na elke servermigratie of CMS-update.

Veelgemaakte fouten

  • - HSTS aanzetten terwijl HTTPS nog niet overal werkt, waardoor bezoekers de site niet meer kunnen openen.
  • - In nginx het sleutelwoord always vergeten, zodat headers ontbreken op fout- en redirectpagina's.
  • - In nginx een add_header in een location-blok plaatsen, waardoor alle headers uit het bovenliggende blok wegvallen.
  • - Een Content-Security-Policy meteen te streng instellen, waardoor eigen scripts, analytics of ingesloten content stoppen met werken.
  • - Headers dubbel instellen, bijvoorbeeld via een CMS-plug-in én via .htaccess, met onvoorspelbaar gedrag tot gevolg.
  • - Na het instellen niet hertesten, zodat een latere migratie of update de headers ongemerkt weer verwijdert.

Veelgestelde vragen

Welke security header moet ik als eerste instellen?

Begin met de eenvoudige headers die zelden iets breken: X-Frame-Options, X-Content-Type-Options, Referrer-Policy en Permissions-Policy. Die kun je vrijwel altijd direct toevoegen. HSTS en Content-Security-Policy bewaar je voor daarna, omdat die meer aandacht en testen vragen.

Kan ik mijn site stukmaken door headers toe te voegen?

Een verkeerd ingestelde Content-Security-Policy kan eigen scripts of ingesloten content blokkeren, en HSTS kan bij ontbrekend HTTPS bezoekers buitensluiten. De andere headers zijn vrijwel risicoloos. Werk daarom in kleine stappen en test na elke wijziging het zichtbare resultaat in de browser.

Werkt dit ook op gedeelde hosting?

Ja, in de meeste gevallen wel. Op gedeelde hosting met Apache zet je de headers in een .htaccess-bestand in de hoofdmap, en de module mod_headers staat daar doorgaans al aan. Heb je geen toegang tot de serverconfiguratie, dan is .htaccess vaak je enige en prima werkbare optie.

Wat doen de fix-generators van CheckBorg precies?

Ze nemen het resultaat van je scan en genereren een kant-en-klaar configuratieblok voor nginx of Apache dat je kunt kopiëren en plakken. Zo voorkom je tikfouten in de waarden en hoef je de syntax niet uit je hoofd te kennen. Deze functie zit in het Pro-pakket; je plaatst de configuratie altijd zelf, zodat je de controle houdt.

Hoe controleer ik of mijn headers echt actief zijn?

Je kunt de respons-headers bekijken in de ontwikkelaarstools van je browser, op het tabblad Netwerk, of via een online scan. Een scan is overzichtelijker omdat hij meteen aangeeft welke headers ontbreken of een verkeerde waarde hebben. Hertest na elke servermigratie of grote update, want die kunnen je instellingen ongemerkt overschrijven.

Verder lezen

Gerelateerde gidsen

Verdiep je verder in websitekwaliteit, vindbaarheid en conversie voordat je de volgende scan draait.

9 min lezen

E-mail deliverability checken: SPF, DKIM, DMARC, MTA-STS en TLS-RPT goed zetten

Leer hoe je e-mail deliverability controleert en verbetert met MX, SPF, DKIM, DMARC, MTA-STS en TLS-RPT, inclusief de exacte DNS-records die je nodig hebt.

Lees verder

9 min lezen

Status-pagina en uptime-badge: zo toon je dat je site het doet

Wat een status-pagina is, waarom uptime-transparantie vertrouwen geeft en hoe je een deelbare status-pagina plus embedbare uptime-badge inzet voor je site.

Lees verder

9 min lezen

Wat is een website scan?

Wat is een website scan? Leer wat er gecontroleerd wordt, wanneer je een scan inzet en hoe je de resultaten omzet naar concrete verbeteringen voor je site.

Lees verder

Wil je direct zien waar jouw website staat?

Start een veilige CheckBorg scan en vertaal technische signalen naar duidelijke prioriteiten.

Start gratis scan