På angrebskortet ligger en tæt plet over ét land, og reglen «forbyd det helt» melder sig af sig selv. Den giver næsten ingenting: at skifte udgangsland koster angriberen få minutter, mens forbuddet rammer dine egne besøgende og dig selv på rejse. Værre endnu: en synlig crawler fra én enkelt sky flytter efter blokeringen over på private adresser og bliver umulig at skelne fra mennesker.

Nedenfor er fem trin, der faktisk giver resultat på den samme server: skær scannerne fra, begræns tempoet, lad være med at skære det nødvendige fra, og bloker rigtigt, hvis det alligevel bliver nødvendigt. Det hele kan kontrolleres og sættes op på én gang.

Trin 1. Se, hvem der rent faktisk skaber pletten

Find først logfilen over forespørgsler. På en server med flere websteder er access.log ofte tom, mens linjerne havner i loggen for den enkelte virtuelle vært:

sudo ls -lS /var/log/apache2/*access*.log /var/log/apache2/*requests*.log 2>/dev/null

I alle de følgende kommandoer indsættes den fil, der kom øverst på listen. Først de førende adresser for døgnet, derefter hvad den øverste rent faktisk beder om:

sudo awk '{print $1}' /var/log/apache2/access.log | sort | uniq -c | sort -rn | head -20
sudo grep '^203\.0\.113\.' /var/log/apache2/access.log | awk '{print $7}' | sort | uniq -c | sort -rn | head -20

Den anden kommando besvarer hovedspørgsmålet. Står der snesevis af forskellige sider fra dit eget websted i udskriften, er det en indholdsindsamler: harmløs, og det er nok ikke at tælle den som besøgende. Står der /wp-login.php, /.env, /phpmyadmin og andet, du slet ikke har, er det en scanner, og den tager trin 2 sig af. Ved nginx ligger loggene i /var/log/nginx/, felterne er de samme.

Trin 2. Et jail mod forespørgsler på noget, du ikke har

Den forespurgte sti kan ikke forfalskes — den er selve hensigten, i modsætning til adressen og User-Agent. Filteret /etc/fail2ban/filter.d/web-probes.local:

[Definition]
failregex = ^<HOST> .* "(GET|POST|HEAD) /(wp-login\.php|wp-admin|xmlrpc\.php|\.env|\.git/|phpmyadmin|administrator/)
ignoreregex =

Jailet /etc/fail2ban/jail.d/web-probes.local:

[web-probes]
enabled  = true
port     = http,https
filter   = web-probes
logpath  = /var/log/apache2/*access.log
maxretry = 1
findtime = 1h
bantime  = 1d

Her er maxretry = 1 berettiget: ingen havner tilfældigt på en andens administrationsside. Anvend det, og kontrollér, at filteret fanger linjer i din egen log:

sudo fail2ban-regex /var/log/apache2/access.log /etc/fail2ban/filter.d/web-probes.local
sudo systemctl reload fail2ban && sudo fail2ban-client status web-probes

Trin 3. Begræns tempoet

Scanneren og crawleren røber sig ved hastighed, uanset hvilket land de kommer fra. Tredive sider i minuttet fra én adresse er en grænse, der ikke rammer et menneske, der bladrer i et katalog:

[http-flood]
enabled  = true
port     = http,https
filter   = apache-overflows
logpath  = /var/log/apache2/site_access.log
maxretry = 30
findtime = 60
bantime  = 1h

Det afgørende er, hvilken log der står i logpath. Falder loggen for selve kontrolpanelet eller administrationsdelen ind under mønsteret, blokerer du dig selv: en enkelt side dér trækker et dusin forespørgsler på stilark og scripts med sig, og tredive når man op på med to klik. Derfor giver man panelet sin egen logfil, der ikke passer på jailets mønster, og statiske filer en lang cachetid, så browseren ikke beder om dem igen ved hvert sideskift. Symptomet, hvis det alligevel sker: HTML-koden kommer frem, udseendet gør ikke, siden hænger. Ophæv blokeringen:

sudo fail2ban-client set http-flood unbanip 203.0.113.10

Trin 4. Beskyt det, der ikke må skæres fra

Skriv undtagelserne ned, før du slår blokeringer til — ellers er det første, de rammer, netop det nødvendige:

[DEFAULT]
ignoreip = 127.0.0.1/8 ::1 203.0.113.0/24 66.249.64.0/19

Hvad der ubetinget hører til på den linje, og hvorfor:

  • Din egen adresse eller kontorets undernet. Den hyppigste årsag til at miste adgang til en server er ens egen regel, ikke et angreb;
  • Området 66.249.64.0/19. Googles søgerobot giver sig til kende via User-Agent, men den del af den, der udfører JavaScript, kommer som en ganske almindelig Chrome/Linux og nævner ikke sig selv. Enhver regel af typen «bloker trafik fra datacentre» rammer netop den, hvorefter sider stille falder ud af indekset. En mistænkelig adresse kan kontrolleres med et omvendt opslag: dig -x 66.249.66.1 +short skal give et navn i zonen googlebot.com;
  • Adresserne, betalingsbeskederne kommer fra. Webhooks fra betalingssystemer kommer fra AWS- og Azure-servere. Lukker du de skyer helt, holder betalingsbekræftelserne op med at nå frem, og du opdager det den dag, en kunde skriver, at pengene er trukket, men adgangen mangler. Områderne står i dokumentationen hos din betalingsudbyder.

Trin 5. Hvis en blokering alligevel er nødvendig — bloker et undernet, ikke et land

En vedvarende fortætning fra ét enkelt net, der holder i dagevis og ledsages af ensartede forespørgsler, er én udøver, der arbejder sig gennem en liste. Det tilfælde blokeres præcist og tidsbegrænset:

sudo ufw deny from 198.51.100.0/22 to any
sudo ufw status numbered

Notér reglens nummer med den anden kommando: blokeringen skal senere ophæves netop gennem det, sudo ufw delete <nummer>. Aftal en frist med dig selv — for eksempel en måned — og skriv ophævelsen i kalenderen. Regler, der er sat «for altid», bliver efter et år til en liste, ingen tør røre, fordi ingen husker, hvad de adresser gjorde for at havne der.

Hvilket undernet der skal blokeres, finder du ud af ud fra adressen fra første trin: whois 198.51.100.17 | grep -iE 'route|cidr|netname'.

Hvad der ændrer sig efter disse fem trin

Scannere skæres fra efter hensigt og ikke efter oprindelse, og fanges ved den første forespørgsel. Crawlere støder ind i hastighedsgrænsen. Søgerobotten og betalingsbeskederne kommer fortsat igennem. Den eneste blokering, der er blevet bred, er præcis, med en kendt frist og en forståelig grund.

Kortet forsvinder ikke af den grund, men dets rolle ændrer sig: det er der ikke for at lukke lande af, men for overhovedet at få øje på fortætningen og sammenligne den med ugen før. Til det skal der en historik til og ikke et øjebliksbillede af det aktuelle døgn. Hvordan sådan et kort ser ud sammen med blokeringsloggen og listen over åbne porte, viser demosiderne nedenfor.