Na mape útokov je hustá škvrna nad jednou krajinou a samo sa ponúka pravidlo „zakázať ju celú“. Neprinesie to takmer nič: zmeniť krajinu výstupu stojí útočníka pár minút, pod zákaz však spadnú vaši vlastní návštevníci a vy sami na cestách. Čo je horšie, viditeľný robot prichádzajúci z jedného cloudu sa po zablokovaní presťahuje na domáce adresy a prestane byť od ľudí rozoznateľný.
Nižšie je päť krokov, ktoré na tom istom serveri výsledok naozaj dajú: odrezať skenery, obmedziť tempo, neodrezať to potrebné a — ak to naozaj treba — zablokovať správne. Všetko sa dá overiť a nastaviť na jedno posedenie.
Krok 1. Pozrieť sa, kto škvrnu vlastne vytvára
Najprv nájdite protokol požiadaviek. Na serveri s viacerými webmi býva access.log prázdny, kým záznamy idú do protokolu konkrétneho virtuálneho hostiteľa:
sudo ls -lS /var/log/apache2/*access*.log /var/log/apache2/*requests*.log 2>/dev/null
Vo všetkých ďalších príkazoch sa dosadzuje súbor, ktorý sa ocitol na začiatku tohto výpisu. Najprv vedúce adresy za deň, potom to, o čo presne žiada tá hore:
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
Druhý príkaz odpovedá na hlavnú otázku. Ak sú vo výstupe desiatky rôznych stránok vášho webu, ide o zberač obsahu: je neškodný a stačí ho nepočítať ako návštevníka. Ak je tam /wp-login.php, /.env, /phpmyadmin a ďalšie veci, ktoré nemáte, ide o skener, a tým sa zaoberá krok 2. Pri nginx ležia protokoly v /var/log/nginx/, polia sú rovnaké.
Krok 2. Jail na požiadavky na to, čo nemáte
Cestu požiadavky nemožno sfalšovať — ona sama je zámerom, na rozdiel od adresy a User-Agenta. Filter /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 =
Jail /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
Tu je maxretry = 1 oprávnené: náhodné prístupy do cudzej administrácie neexistujú. Použiť a overiť, že filter zaberá na záznamy vo vašom protokole:
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
Krok 3. Obmedziť tempo
Skener aj robot sa prezradia rýchlosťou, nezávisle od toho, z akej sú krajiny. Tridsať stránok za minútu z jednej adresy je prah, ktorý sa človeka listujúceho katalógom nedotkne:
[http-flood]
enabled = true
port = http,https
filter = apache-overflows
logpath = /var/log/apache2/site_access.log
maxretry = 30
findtime = 60
bantime = 1h
Kľúčové je, ktorý protokol je uvedený v logpath. Ak pod masku spadne protokol samotného riadiaceho panela alebo administrácie, zablokujete sami seba: jediná jeho stránka za sebou ťahá desiatku požiadaviek na štýly a skripty a tridsať sa nazbiera na dve kliknutia. Preto sa panelu dáva vlastný súbor protokolu, ktorý maske jailu nezodpovedá, a statickým súborom dlhý čas platnosti vo vyrovnávacej pamäti, aby ich prehliadač nežiadal znovu pri každom prechode. Príznak, ak k tomu predsa len došlo: HTML dorazí, vzhľad nie, stránka visí. Zrušenie blokovania:
sudo fail2ban-client set http-flood unbanip 203.0.113.10
Krok 4. Ochrániť to, čo sa nesmie odrezať
Skôr než blokovania zapnete, zapíšte výnimky — inak pod ne ako prvé spadne to potrebné:
[DEFAULT]
ignoreip = 127.0.0.1/8 ::1 203.0.113.0/24 66.249.64.0/19
Čo v tomto riadku musí byť bezpodmienečne a prečo:
- Vaša vlastná adresa alebo podsieť kancelárie. Najčastejšou príčinou straty prístupu k serveru je vlastné pravidlo, nie útok;
- Rozsah
66.249.64.0/19. Vyhľadávací robot Google sa spozná podľa User-Agenta, ale tá jeho časť, ktorá vykonáva JavaScript, prichádza ako obyčajnýChrome/Linuxa nepredstavuje sa. Akékoľvek pravidlo typu „blokovať prevádzku z dátových centier“ zasiahne práve ju, načo stránky ticho vypadnú z indexu. Podozrivú adresu možno overiť spätnou požiadavkou:dig -x 66.249.66.1 +shortmá vrátiť meno v zónegooglebot.com; - Adresy platobných oznámení. Webhooky platobných systémov prichádzajú zo serverov AWS a Azure. Ak tieto cloudy uzavriete celé, potvrdenia platieb prestanú dochádzať, a dozviete sa to vo chvíli, keď zákazník napíše, že peniaze odišli, ale prístup nemá. Rozsahy sa berú z dokumentácie vášho poskytovateľa platieb.
Krok 5. Ak je blokovanie predsa len nutné — blokujte podsieť, nie krajinu
Trvalé zahustenie z jedinej siete, ktoré drží celé dni a sprevádzajú ho rovnorodé požiadavky, je jeden vykonávateľ prechádzajúci zoznam. Takýto prípad sa blokuje bodovo a na čas:
sudo ufw deny from 198.51.100.0/22 to any
sudo ufw status numbered
Druhým príkazom si zapamätajte číslo pravidla: blokovanie bude treba zrušiť práve cezeň, sudo ufw delete <číslo>. Dohodnite sa sami so sebou na lehote — napríklad mesiac — a zrušenie si zapíšte do kalendára. Pravidlá nastavené „navždy“ sa po roku premenia na zoznam, ktorého sa nikto neodváži dotknúť, lebo si nikto nepamätá, za čo sa tie adresy doň dostali.
Ktorú podsieť blokovať, zistíte podľa adresy z prvého kroku: whois 198.51.100.17 | grep -iE 'route|cidr|netname'.
Čo sa po týchto piatich krokoch mení
Skenery sa odrezávajú podľa zámeru, a nie podľa pôvodu, a chytajú sa pri prvej požiadavke. Roboty narazia na obmedzenie tempa. Vyhľadávací robot a platobné oznámenia ďalej prechádzajú. Jediné blokovanie, ktoré zostalo široké, je bodové, so známou lehotou a zrozumiteľným dôvodom.
Mapa pritom nikam nemizne, ale jej úloha sa mení: nie je tu na to, aby zatvárala krajiny, ale aby zahustenie vôbec zaznamenala a porovnala ho s tým, čo bolo pred týždňom. Na to je potrebná história, a nie snímka aktuálneho dňa. Ako taká mapa vyzerá vedľa protokolu blokovaní a zoznamu otvorených portov, ukazujú ukážkové stránky nižšie.