Hyökkäyskartalla on tiheä läiskä yhden maan kohdalla, ja sääntö ”estetään se kokonaan” tarjoutuu itsestään. Se ei tuota juuri mitään: lähtömaan vaihtaminen vie hyökkääjältä muutaman minuutin, kun taas eston alle jäävät omat kävijäsi ja sinä itse matkoilla. Vielä pahempaa: näkyvä indeksointirobotti, joka tulee yhdestä pilvestä, siirtyy eston jälkeen kotiliittymien osoitteisiin eikä sitä enää erota ihmisistä.

Alla on viisi askelta, jotka samalla palvelimella todella tuottavat tuloksen: katkaise skannerit, rajoita tahtia, älä katkaise tarpeellista ja — jos esto sittenkin tarvitaan — estä oikein. Kaiken voi tarkistaa ja asettaa yhdellä istumalla.

Askel 1. Katso, kuka läiskän oikeasti synnyttää

Etsi ensin pyyntöloki. Palvelimella, jolla on useita sivustoja, access.log on usein tyhjä, kun taas rivit menevät kunkin virtuaalipalvelimen omaan lokiin:

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

Kaikissa seuraavissa komennoissa käytetään sitä tiedostoa, joka nousi listan kärkeen. Ensin vuorokauden kärkiosoitteet, sitten se, mitä ylimmäinen oikeastaan pyytää:

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

Toinen komento vastaa pääkysymykseen. Jos tulosteessa on kymmeniä eri sivuja omalta sivustoltasi, kyseessä on sisällönkerääjä: se on vaaraton, ja riittää, ettei sitä lasketa kävijäksi. Jos siellä on /wp-login.php, /.env, /phpmyadmin ja muuta, mitä sinulla ei ole, kyseessä on skanneri, ja sen hoitaa askel 2. Nginxissä lokit ovat hakemistossa /var/log/nginx/, kentät ovat samat.

Askel 2. Jail pyynnöille sellaiseen, mitä sinulla ei ole

Pyydettyä polkua ei voi väärentää — se on itse aikomus, toisin kuin osoite ja User-Agent. Suodatin /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

Tässä maxretry = 1 on perusteltu: kukaan ei päädy vahingossa toisen hallintapaneeliin. Ota käyttöön ja varmista, että suodatin osuu oman lokisi riveihin:

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

Askel 3. Rajoita tahtia

Skanneri ja indeksointirobotti paljastuvat nopeudestaan riippumatta siitä, mistä maasta ne tulevat. Kolmekymmentä sivua minuutissa yhdestä osoitteesta on raja, joka ei kosketa luetteloa selaavaa ihmistä:

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

Ratkaisevaa on, mikä loki on merkitty kohtaan logpath. Jos maskin alle osuu itse hallintapaneelin tai ylläpito-osan loki, estät itsesi: yksi sen sivu vetää mukanaan kymmenkunta pyyntöä tyyleihin ja skripteihin, ja kolmekymmentä kertyy parilla napsautuksella. Siksi paneelille annetaan oma lokitiedosto, joka ei osu jailin maskiin, ja staattisille tiedostoille pitkä välimuistin voimassaoloaika, jottei selain pyydä niitä uudelleen joka sivunvaihdolla. Oire, jos niin kuitenkin käy: HTML tulee perille, ulkoasu ei, sivu jää roikkumaan. Eston purku:

sudo fail2ban-client set http-flood unbanip 203.0.113.10

Askel 4. Suojaa se, mitä ei saa katkaista

Kirjaa poikkeukset ennen kuin otat estot käyttöön — muuten niiden alle jää ensimmäisenä juuri tarpeellinen:

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

Mitä tällä rivillä pitää ehdottomasti olla ja miksi:

  • Oma osoitteesi tai toimiston aliverkko. Yleisin syy palvelimen käyttöoikeuden menettämiseen on oma sääntö, ei hyökkäys;
  • Alue 66.249.64.0/19. Googlen hakurobotti tunnistautuu User-Agentilla, mutta se sen osa, joka suorittaa JavaScriptin, saapuu tavallisena Chrome/Linux -selaimena eikä kerro itsestään. Mikä tahansa sääntö tyyliin ”estetään liikenne konesaleista” osuu juuri siihen, minkä jälkeen sivut putoavat hiljaa pois hakemistosta. Epäilyttävän osoitteen voi tarkistaa käänteisellä kyselyllä: dig -x 66.249.66.1 +short palauttaa nimen vyöhykkeeltä googlebot.com;
  • Maksuilmoitusten osoitteet. Maksujärjestelmien webhookit saapuvat AWS- ja Azure-palvelimilta. Jos suljet nämä pilvet kokonaan, maksuvahvistukset lakkaavat tulemasta perille, ja saat sen tietää silloin, kun asiakas kirjoittaa, että rahat on veloitettu mutta käyttöoikeutta ei ole. Alueet löytyvät maksupalveluntarjoajasi ohjeista.

Askel 5. Jos esto sittenkin tarvitaan — estä aliverkko, älä maata

Pysyvä tihentymä yhdestä verkosta, joka kestää päiviä ja johon liittyy samankaltaisia pyyntöjä, on yksi toimija, joka käy listaa läpi. Tällainen tapaus estetään täsmällisesti ja määräajaksi:

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

Merkitse toisella komennolla säännön numero muistiin: esto on myöhemmin purettava juuri sen kautta, sudo ufw delete <numero>. Sovi itsesi kanssa määräajasta — vaikkapa kuukausi — ja merkitse purku kalenteriin. ”Ikuisiksi ajoiksi” asetetut säännöt muuttuvat vuodessa listaksi, johon kukaan ei uskalla koskea, koska kukaan ei muista, mistä nuo osoitteet sinne joutuivat.

Minkä aliverkon estää, selviää ensimmäisen askeleen osoitteesta: whois 198.51.100.17 | grep -iE 'route|cidr|netname'.

Mikä näiden viiden askeleen jälkeen muuttuu

Skannerit katkaistaan aikomuksen eikä alkuperän perusteella, ja ne jäävät kiinni ensimmäisestä pyynnöstä. Indeksointirobotit törmäävät tahdin rajaan. Hakurobotti ja maksuilmoitukset pääsevät edelleen läpi. Ainoa laajaksi jäänyt esto on täsmällinen, tunnetulla määräajalla ja ymmärrettävällä syyllä.

Kartta ei tästä katoa mihinkään, mutta sen rooli muuttuu: sitä ei tarvita maiden sulkemiseen vaan siihen, että tihentymä ylipäätään huomataan ja sitä verrataan viikon takaiseen. Siihen tarvitaan historia eikä kuluvan vuorokauden tilannekuva. Miltä tällainen kartta näyttää estolokin ja avointen porttien luettelon rinnalla, näkyy alla olevilla esittelysivuilla.