Koputtelijoita ovella

Mitä pienen sivuston palvelinlokeista löytyy ja miten turha liikenne karsitaan

4 min lukuaika

VR:n lippuautomaassa kaatunut sovellus, jonka lokietoja ruudulla, kuvituskuva

Vähän sen jälkeen kun julkaisin tämän sivuston, vilkaisin mitä palvelimen lokiin on kertynyt. Odotin näkeväni lähinnä hakukoneiden indeksoijia ja ehkä muutaman lukijan. Kuitenkin jo ensimmäisen tunnin aikana yksi ainoa IP-osoite oli tehnyt sivustolle yli 30 000 pyyntöä, eikä se ollut edes pahin tapaus.

Kaikki julkiseen internetiin kytketyt palvelimet saavat tällaista liikennettä. Botit käyvät läpi koko osoiteavaruuden ja kokeilevat jokaista vastaan tulevaa palvelinta. Sillä ei ole väliä, onko kyseessä iso verkkokauppa vai pieni kotisivu. Tähän muistiinpanoon kokosin, mitä lokeista löytyi ja miten turhaa liikennettä voi karsia.

Kerron periaatteet ja yleiset työkalut, mutta en tarkkoja asetuksia. Turvatoimien yksityiskohdat ovat juuri sitä tietoa, josta koputtelijat hyötyisivät.

Miten lokia luetaan

Nginx kirjoittaa oletuksena jokaisen pyynnön tiedostoon /var/log/nginx/access.log. Yksi rivi näyttää tältä (IP-osoite on vaihdettu esimerkkiosoitteeksi):

203.0.113.7 - - [29/Oct/2026:07:24:35 +0000] "GET /.env HTTP/1.1" 444 0 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) ... Chrome/116.0.5845.140 Safari/537.36"

Rivin alussa on pyytäjän IP-osoite ja sen jälkeen kellonaika UTC-aikana. Lainausmerkeissä on itse pyyntö, eli metodi, polku ja protokolla. Sitä seuraavat vastauksen tilakoodi ja vastauksen koko tavuina. Viimeisinä ovat referer eli sivu, jolta pyyntö tuli, ja user agent eli se, mitä asiakas väittää olevansa.

User agentiin ei kannata luottaa. Skannerit esiintyvät usein tavallisina selaimina.

Mitä koputtelijat etsivät

Suurin osa pyynnöistä ei liity sivustoon mitenkään. Botit kokeilevat samoja polkuja kaikkialla siltä varalta, että jokin niistä osuu:

WordPressin kirjautuminen ja hallinta, kuten /wp-login.php ja /xmlrpc.php. WordPress on niin yleinen, että sitä kokeillaan kaikilta palvelimilta.

Salaisuuksia sisältävät tiedostot, kuten /.env ja /.git/config. Niissä voi olla joskus tietokantasalasanoja ja API-avaimia, jos ne ovat vahingossa jääneet näkyviin.

Varmuuskopiot ja tietokantadumpit, kuten /backup.zip ja /dump.sql.

Hallintapaneelit, kuten phpMyAdmin, ja tunnetut haavoittuvat polut eri ohjelmistoista.

Avoimen välityspalvelimen testit. CONNECT-pyynnöllä botti kokeilee, voisiko palvelimen kautta ohjata omaa liikennettään muualle.

Pyynnöt suoraan IP-osoitteeseen ilman verkkotunnusta. Oikea lukija tulee aina nimellä, joten nämä ovat käytännössä aina skannereita.

Tämä sivusto on tehty Kirbyllä, joten mikään näistä ei toimisi siihen. Jokainen turha pyyntö kuitenkin herättää PHP:n, joka hakee Kirbyn kautta 404-sivun. Kymmenillä tuhansilla pyynnöillä palvelin tekee paljon turhaa työtä. Oma tavoitteeni on pyörittää sivustoa mahdollisimman pienillä resursseilla.

Kolme kerrosta

Ratkaisin asian kolmella kerroksella, jotka ovat kevyimmästä järeimpään. Jokainen niistä toimii myös yksinään.

1. Verkkopalvelin katkaisee tunnetut koputukset. Nginxissä tunnettuihin skannauspolkuihin vastataan erikoiskoodilla 444. Silloin Nginx sulkee yhteyden vastaamatta mitään, eikä pyyntö koskaan päädy PHP:lle. Nämä osumat kirjataan omaan lokitiedostoonsa. Periaate näyttää tältä:

location ~* \.(?:php\d?|asp|aspx|jsp|cgi|env)$ {
    access_log /var/log/nginx/probe.log;
    return 444;
}

Esimerkki sopii sivustolle, jonka ainoa PHP-tiedosto on index.php ja jolla on oma tarkka location = /index.php -lohkonsa. Nginx käyttää ensimmäistä täsmäävää regex-lohkoa, joten estosääntöjen pitää olla ennen muita regex-lohkoja.

2. Fail2ban bannaa toistuvat yrittäjät. Fail2ban seuraa lokeja ja lisää palomuuriin eston IP-osoitteille, jotka toistuvasti tekevät jotain epäilyttävää. Kun ensimmäinen kerros kirjaa skannaukset omaan lokiinsa, Fail2banin säännöksi riittää, että jokainen rivi tässä lokissa on osuma. Fail2ban osaa myös pidentää bannia joka kerta, kun sama osoite palaa.

3. Datakeskusverkkojen esto. Suuri osa koputuksista tulee muutaman pilvipalvelun konesaleista. Yksittäisten osoitteiden estäminen ei auta, jos botti saa uuden osoitteen samasta verkosta. Jokaisella verkko-operaattorilla on kuitenkin oma AS-numeronsa (ASN), ja sen alle rekisteröidyt IP-alueet voi hakea esimerkiksi RIPEstatista. Pieni skripti hakee valitsemieni verkkojen IP-alueet kerran viikossa ja estää niiden liikenteen palomuurissa kokonaan.

Kolmas kerros on järein, koska se estää myös mahdolliset oikeat kävijät, jotka käyttävät esimerkiksi VPN-palvelua samassa konesalissa. Suomenkieliselle henkilökohtaiselle sivustolle se on hyväksyttävä hinta. Ennen kuin estää mitään, kannattaa katsoa omista lokeista, mistä liikenne oikeasti tulee. Mitään listaa ei kannata kopioida muualta sokkona.

Huomioitavia asioita

Nginx ei lue .htaccess-tiedostoja. Kirbyn mukana tuleva .htaccess estää pääsyn sisäisiin kansioihin, mutta vain Apachessa. Nginxissä samat säännöt pitää kirjoittaa itse. Muuten esimerkiksi palvelimen hakemistoon päätyneet asennusohjeet näkyvät kaikille.

Palomuurin uudelleenlataus voi pyyhkiä estot. Debianissa ja Ubuntussa systemctl reload nftables lukee tiedoston /etc/nftables.conf, jonka ensimmäinen rivi on flush ruleset. Se tyhjentää koko palomuurin, myös Fail2banin ja muiden työkalujen omat taulut. Virheilmoitusta ei tule, mutta estot ovat poissa, kunnes kyseiset palvelut käynnistetään uudelleen.

Oman sivuston testaaminen voi bannata itsensä. Kun testasin skannauspolkuja curlilla kotoa, tajusin olevani juuri sellainen osoite, jonka Fail2ban on tarkoitus bannata. Fail2banin ignoreip-asetukseen voi lisätä IP-osoitteen lisäksi myös DNS-nimen. Jos kotiliittymällä on dyn-dns-nimi esimerkiksi VPN:n takia, saman nimen voi antaa Fail2banille, ja se seuraa vaihtuvaa osoitetta itsestään.

Pientä sivustoa tuskin kukaan on murtamassa henkilökohtaisesti. Botit kuitenkin yrittävät väsymättä, ja jokainen unohtunut .env tai päivittämätön lisäosa löytyy ennen pitkää. Tärkein suoja on se, ettei palvelimella ole mitään löydettävää. Koputusten karsiminen kevyentää palvelimen kuormaa ja siistii lokeja, niin että oikeat ongelmat erottuvat.