Een Nginx-website beschermen tegen een applicatieaanval (L7)

Gepubliceerd op 21/08/2026 Bijgewerkt op 06/10/2026 51 weergaven
Sécurité VPS Linux Nginx DDoS

Niet alle aanvallen lijken op elkaar. Een volumetrische aanval probeert de netwerkverbinding te verzadigen: dat is een file op de snelweg, en de bescherming van By-Hoster vangt die stroomopwaarts op, zonder dat u iets hoeft te doen.

Een applicatieaanval, ook wel laag-7-aanval genoemd, is anders. Het verkeer blijft bescheiden, maar elk verzoek is kostbaar: een zoekopdracht, een aanmeldpagina, een winkelwagen. Voor het netwerk zijn dat normale bezoekers. Pas op het niveau van uw webserver wordt de aard van het verkeer zichtbaar, en daar moet u dus ingrijpen.

Hoe weet ik wat mijn server werkelijk treft?

Verander niets zolang u niet weet wat er binnenkomt. Een willekeurig ingestelde regel blokkeert vaak uw echte bezoekers zonder de aanvaller te hinderen.

De meest actieve IP-adressen:

awk '{print $1}' /var/log/nginx/access.log | sort | uniq -c | sort -rn | head -20

De meest opgevraagde URL's:

awk -F'"' '{print $2}' /var/log/nginx/access.log | sort | uniq -c | sort -rn | head -20

Het verkeer van de laatste minuut, om de intensiteit te beoordelen:

tail -n 100000 /var/log/nginx/access.log | awk '{print $4}' | uniq -c | tail -20

U zoekt naar een patroon: een handvol zeer spraakzame adressen, één URL die steeds opnieuw wordt bestookt, overal dezelfde user-agent. Dat patroon bepaalt de regel, niet andersom.

Controleer ook wat er werkelijk overbelast raakt:

uptime
systemctl status php8.3-fpm --no-pager

Vaak is het niet Nginx dat bezwijkt, maar PHP of de database erachter.

Hoe beperk ik het aantal verzoeken per adres in Nginx?

Nginx kan verzoeken per adres tellen en de verzoeken afremmen die de grens overschrijden. De zones declareert u in het blok http (bestand /etc/nginx/nginx.conf):

http {
    limit_req_zone  $binary_remote_addr zone=req_par_ip:10m rate=10r/s;
    limit_conn_zone $binary_remote_addr zone=conn_par_ip:10m;
}

Daarna past u ze toe in het blok van de website:

server {
    limit_req  zone=req_par_ip burst=20 nodelay;
    limit_conn conn_par_ip 20;
}

Wat dat concreet betekent:

Instelling Effect
rate=10r/s 10 verzoeken per seconde per adres in normaal gebruik
burst=20 staat een piek van 20 verzoeken boven het ritme toe
nodelay handelt de piek direct af in plaats van hem te spreiden
limit_conn 20 maximaal 20 gelijktijdige verbindingen per adres

Een zone van 10m onthoudt ongeveer 160.000 adressen, ruim voldoende.

burst zonder nodelay zet verzoeken in een wachtrij: de website wordt traag in plaats van te weigeren. Met nodelay komt een normale bezoeker die een pagina met twintig bronnen laadt zonder vertraging door, terwijl een bot die blijft aandringen een 503-fout krijgt.

Bescherm de URL's die echt kostbaar zijn strenger, in plaats van de hele website:

location = /wp-login.php {
    limit_req zone=req_par_ip burst=3 nodelay;
}

Hoe test ik de Nginx-configuratie voordat ik die toepas?

Met nginx -t, dat de syntaxis valideert zonder iets toe te passen, en daarna een herlading in plaats van een herstart.

nginx -t

Deze opdracht valideert de syntaxis zonder iets te onderbreken. Het antwoord moet syntax is ok en daarna test is successful zijn. Pas daarna:

systemctl reload nginx

reload herlaadt de configuratie zonder lopende verbindingen te verbreken, in tegenstelling tot restart. Midden in een aanval maakt dat verschil uit.

Houd in de gaten wat er wordt geweigerd:

grep "limiting requests" /var/log/nginx/error.log | tail -20

Ziet u uw eigen adressen of die van uw klanten verschijnen, dan is de limiet te laag. Verhoog hem.

Hoe serveer ik dezelfde pagina minder vaak?

De beste manier om een aanval op te vangen is vaak om de pagina niet bij elk verzoek opnieuw te berekenen. Een pagina die 60 seconden in de cache staat, kost vrijwel niets, hoeveel verzoeken er ook binnenkomen.

http {
    proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=site:50m inactive=10m;
}
location / {
    proxy_cache site;
    proxy_cache_valid 200 60s;
    proxy_cache_use_stale error timeout updating;
}

proxy_cache_use_stale is de regel die u redt: reageert de backend niet meer, dan blijft Nginx de laatst bekende versie serveren in plaats van een foutmelding.

Bij WordPress, PrestaShop of Laravel bereikt u met een applicatiecachemodule hetzelfde effect, met minder risico op neveneffecten.

Hoe blokkeer ik hardnekkige adressen met fail2ban?

Beperken vertraagt; blokkeren stopt. fail2ban leest de logboeken en voegt een firewallregel toe tegen adressen die de limiet te vaak activeren.

apt install fail2ban

In /etc/fail2ban/jail.local:

[nginx-limit-req]
enabled  = true
filter   = nginx-limit-req
logpath  = /var/log/nginx/error.log
maxretry = 10
findtime = 60
bantime  = 3600
systemctl restart fail2ban
fail2ban-client status nginx-limit-req

Hardop gelezen betekent de regel: een adres dat de beperking 10 keer in 60 seconden activeert, wordt een uur geblokkeerd.

Welke instellingen moet u vermijden bij een applicatieaanval?

Deze instellingen circuleren veel en doen meer kwaad dan goed.

Te vermijden Waarom
curl en wget blokkeren op user-agent Een aanvaller wisselt met één regel van user-agent. U daarentegen breekt uw monitoring, uw betaalwebhooks en uw back-upscripts.
client_max_body_size 1k Elke upload van een afbeelding, elk wat langer formulier en elke CMS-update mislukt.
allow op een subnet en daarna deny all U sluit de website af voor heel internet, dus voor uw bezoekers. Gebruik dit patroon alleen voor beheer-URL's.
Uit reflex hele landen blokkeren Veel valspositieven, en aanvallers huren overal machines.
Logboeken uitschakelen “voor de prestaties” U verliest de enige manier om te begrijpen wat er met u gebeurt.

Een eenvoudige regel: elke maatregel die breder blokkeert dan het waargenomen patroon, betaalt u met verloren klanten.

Wanneer opent u een ticket bij ons?

Wanneer het probleem verder gaat dan wat u op de machine kunt oplossen: verzadigde verbinding, langdurige aanval of duizenden adressen.

Open een ticket als:

  • de machine ondanks deze instellingen onbereikbaar blijft;
  • het verkeer de netwerkverbinding verzadigt nog voordat het Nginx bereikt;
  • de aanval aanhoudt en van duizenden verschillende adressen komt.

Voeg aan het ticket de logfragmenten uit stap 1 en het betreffende tijdvenster toe. Daarmee kunnen wij stroomopwaarts ingrijpen, op het netwerk, waar u zelf niet bij kunt.

Had u iets aan dit artikel?