tavis nörttimaailmassa

EksisONE - artikkeleita ja ohjeita nörttimaailmasta

User-agent esto Nginx:ssä

Pahat ja ahneet botit, crawlerit ja spiderit ovat riesa jokaiselle websivustoa ylläpitävälle. Ne varastavat sisältöä omiin tarkoituksiinsa tai yrittävät murtaa sivuston. Jos perusturvasta on pidetty huolta, niin murtoyritykset jäävät tuloksettomiksi. Se toki edellyttää, että tunnukset ja salanat eivät ole murrettavissa ja päivitykset ovat ajantasalla. Kuormaa ja logintäytettä niistä kuitenkin tulee, vaikkakin se on kiusana vähäisemmästä päästä. Suurempi ongelma kuormalle ja rasitukselle ovat kiinalaiset hakukoneet sekä kaikki SEO-spiderit. Toki globaalia mainostusta tekeville on hyödyllistä, että moista kattavaa indeksointia tehdään, mutta silti sen maksaa sivuston omistaja saamatta mitään hyötyä. Siksi ne kannattaa aina estää ja sallia vain itselle hyödylliset.

Jos webserverinä on Nginx, niin esto on melkoisen helppo tehdä käyttäjäagentin eli user-agentin avulla. Osa kytkee serveripään estot IP-osoitteiden estoon Fail2bannin avulla, mutta siinä on tehokkuudestaan huolimatta selvä vaje.

Fail2ban on aina myöhässä. Se lukee logeja ja bannaa aikaisintaan toisesta yrityksestä. IP-osoitteen bannaamista vaikeuttaa lisäksi VPN-palvelut, jonka takia IP-osoitteet voivat olla melkein mitä tahansa. Toki suurin osa, varsinkin vihamielisessä aukkojen metsästyksessä, käyttää omaa tai omistamansa virtuaaliserverin IP-osoitetta uhan vaan ammattitaidottomuuttaan, mutta lähes säännömukaisesti näkee myös saman aukon metsästyksessä miten IP vaihtuu aina kahden yrityksen jälkeen.

User-agent on tunniste, jonka jokainen saapuva ohjelmisto ilmoittaa. Ei sekään ole yhtään IP-osoitteen bannaamista varmempi tapa, koska sen pystyy muuttamaan ja monet yrittäjät valehtelevat bottiaan tavalliseksi kävijäksi. Mutta jos unohdetaan murtoyritykset, niin muiden huonosti käyttäytyvien bottien estämisessä uswer-agent on paljon toimivampi kuin IP-osoite. Se johtuu siitä, että kaikilla isoilla spidereita ja crawlereita käyttävillä yrityksillä on melkoinen IP-arsenaalia takanaan. Ne pitäisi ajan myötä sulkea jokainen sitä mukaa kun ilmestyvät linjoille. User-agent sen sijaan pysyy samana koko ajan.

Tämä on selvä ero, joka on ymmärrettävä. Murtoyritysten estäminen tarvitsee erilaiset työkalut kuin muutoin ahneiden, mutta sinällään rehellisten bottien estäminen. Kun halutaan saada kaista ja serverin tehot ihmiskäyttäjille eikä maksaa jonkun muun firman liiketoiminnan tukemisesta, niin Nginx on näppärä työkalu bottien estämisessä.

Bad bot list

Ensin tarvitaan lista niistä user agenteista, joita botit ilmoittavat. Voit penkoa niitä omista logeistasi ja seurata liikennettäsi (melkoisen koukuttavaa, varsinkin väsyneenä) tai googlettaa valmiita listoja. Ne voivat sitten olla henkeäsalpaavan pitkiä ja sisältää sellaisiakin botteja, jotka ovat kuolleet sukupuuttoon jo aikoja sitten. Pituus ei sinällään ole ongelma, mutta jos sinulla on jotain erityisvaatimuksia, niin sallittavien löytäminen voi olla työlästä.

Minä julkaisen parillakin sivustollani podcastejä, joten sallin osan podcast-feedejä lukevien bottien saapumisen. Osan kiellän, varsinkin silloin kun ne eivät palvele minua tai oletettua kävijäkuntaani mitenkään. Suljen ulkopuolelle esimerkiksi saksalaisitalialaisbelgialaisen nettiradion, koska minulla ei ole kuulijoita heidän kauttaa, eikä äkkiä tule. Sinänsä syötteen lukeminen ei ole mikään iso asia, mutta kyseessä on periaatteellinen asia: en halua palvella sekunnin murto-osaakaan bottia, joka käy noin puoli tusinaa kertaa päivässä vain siksi, että kaupallinen radioasema voi mainostaa tuhansia podcastejä.

Oma listani sisältää käytännössä sellaisia, jotka ovat aidosti käyneet sivuillani. Estän kaikki kaupalliset SEO- ja avainsana-crawlerit sekä kiinalaiset ja venäläiset hakurobotit – pääsääntöisesti siksi, että ne ovat törkeän ahkeria ja suurimpia syyllisiä sivustojen hidastumiseen liian kuorman takia. Lisäksi estän ne kolkuttajat, jotka ovcat tarpeeksi hölmöjä kertomaan työkalunsa oikean user-agentin. Nyrkkisääntö on, että jos botti ei palvele minua mitenkään, niin estän sen.

Periaatteessa estolistalta voisi jättää pois sellaisten bottien user-agentit, jotka noudattavat robots.txt tiedostoa. Kyse on kuitenkin vain periaatteesta, koska pahantahtoiset SEO-yritykset valehtelevat aivan sutjakkaasti olevansa Google tai tavallinen käyttäjä kännykällään. Kun estolistalle laitetaan mukaan muutoin kohteliaasti käyttäytyvät, mutta turhat, spiderit, niin saadaan estettyä valehtelijatkin.

Ylipäätään robots.txt on hyödyllinen vain  Googlen ja muutaman muun laillisen botin ohjaamisessa. Toki Disallow: / pysäyttää listalla olemattomat rehelliset botit, mutta sopivan kattavalla kieltoluettelolla niitä ei montaa ole – tosin, uusia SEO- ja markkinointiyrityksiä syntyy koko ajan, joten vähintään täytyy seurata osumia robots.txt tiedostoon ja laittaa estoon uudet tulokkaat.

Voit kopioida itse käyttämäni blokkauslistan täältä: blockbots.conf

Nginx:n asettaminen

Laitetaan blokkilista serverille. Voit toki käyttää FTP:tä ja editoida vaikka Notepad++ avulla (joka ei ole sinällään huono työnkulku Windows-koneissa), mutta annan esimerkit shellin kautta. Itse kirjaudun aina root-tunnuksilla, mutta jos sinä et, niin muista sudo tai su. Järjestelmänä on Ubuntu ja alustana DigitalOceanin VPS eli droplet. Homma toimii tismalleen samoin jokaisessa linuxissa, mutta toki polut ja muokkauspolut vaihtelevat.

  • Tehdään lista:
nano /etc/nginx/conf.d/blockbots.conf

Kopioi sinne haluamasi user-agentit. Noudata muotoa


map $http_user_agent $bad_bot {
  default 0;
  "~*(?:\b)DotBot(?:\b)"   1;   # estetään, jos user agentissa on mukana DotBot
}

Kun tiedosto laitetaan conf.d hakemistoon, niin Nginx lataa user agentit automaattisesti muistiin ilman, että sitä täytyy erikseen määrätä jokaisessa virtual hostissa.

Lainausmerkit sallivat mm. välilyönnit user agentin merkkijonossa. Jos et käytä hipsuja, niin sinun täytyy käyttää aina escape-merkkiä \ ennen välilyöntiä – muutoin Nginx yrittää käyttää välilyontiä erottamaan muuttujan sen arvosta.

~* sallii olla piittaamatta kirjainkoosta. Jos jätät asteriskin * pois, niin siitä tulee kirjainkokoriippuvainen. Olen silti käyttänyt isoja kirjaimia luettavuuden takia.

(?:\b) aloittaa ja lopettaa sanat. Sitä ei välttämättä tarvita, mutta estää hieman vahinkopositiivisia.

  • Säädetään Nginxiä:
nano /etc/nginx/nginx.conf

Lisää tämä http osioon:


server_names_hash_bucket_size 64;
server_names_hash_max_size 4096;
variables_hash_max_size 4096;
variables_hash_bucket_size 4096;

Varmista, että sieltä löytyy myös:

include /etc/nginx/conf.d/*.conf;
  • Bannattavien user agentien lista täytyy ottaa käyttöön jokaisessa virtual hostissa erikseen. Nginx sallii huomattavan harvoin mitään globaalisti.
nano /etc/nginx/sites-available/example.com.conf

Lisää tämä server osioon:


# Estetään pahat botit
   if ($bad_bot = 1) {
      return 444;
   }

Jos laitat sen ennen location määrityksiä, niin esto kohdistuu sivuston kaikkiin osiin.

Jos (ja kun…) sinulla on portille 80 uudelleenohjaus porttiin 443 eli kummallekin oma server osio, niin laita bottiesto myös portin 80 server osioon ennen uudelleenohjausta porttiin 443. Silloin saat estettyä botit heti serverin kynnyksellä riippumatta kumpaa kautta tulevat.

Voit käyttää muutakin virhekoodia kuin 444. Se on Nginxin käyttämä epästandardi http status, joka käskee serveriä katkaisemaan yhteyden vastaamatta mitenkään takaisinpäin. Ainoa merkki jää Nginxin logeihin. Botin kannalta yhteyttä ei siten koskaan muodostunut. Error 444 on tehty nimenomaan käytettäväksi mm. haitallisia botteja vastaan.

  • Otetaan esto käyttöön varmistamalla, että ei ole tullut kirotusvirheitä ja käynnistämällä Nginx uudestaan:
nginx -t
systemctl reload nginx
  • Testaa vielä toiminta. Komenna shellissä:
curl -I https://www.example.com -A "GoogleBot"

Sinun pitäisi saada vastaukseksi 200 sekä header-tiedot.

curl -I https://www.example.com -A "DotBot"

Vastauksen pitäisi olla tämänkaltainen:

curl: (92) HTTP/2 stream 0 was not closed cleanly: PROTOCOL_ERROR (err 1)

Voit testata toiminnan selaimellakin. Esimerkiksi Edgessä painat ensin F12, että pääset kehittäjänäkymään. Välilehden Emulointi alta löydät otsikon Tila, Siinä pystyt muuttamaan käyttäjäagentin merkkijonoa.