Een DDOS van de Googlebot?

Normaal is Google een van je betere vrienden op het internet, maar enkele weken geleden liepen we op het internet tegen wat vreemds aan. Onze monitoring alarmeerde ons dat in de afgelopen dagen het CPU-gebruik van één van onze websites geleidelijk aan steeds verder omhoog liep en we dagelijks een duizelingwekkend aantal van bijna 1 miljoen aantal gecrawlde pagina's per dag (!) hadden en een meer dan 25 Gb aan data werd gedownload op dagelijkse basis. Na een korte analyse van onze logfiles leek het er ook nog eens op dat al dat verkeer gegenereerd werd door een Googlebot (of iets of iemand die zich voordeed als Googlebot).

De getroffen website

De website is een productenwebsite voor een Nederlandse meubelmerk. De website bevat ongeveer 300 meubels, inclusief filtering op drie categoriëen. De website is in drie talen beschikbaar, en bevat naast de 300 producten ongeveer nog 100 andere contentpagina’s.

Een DDOS door Google

Omdat we twijfelden of het mogelijk zou zijn dat Googlebot ons in deze mate zou “aanvallen”, hebben we als eerste geverifieerd of de requests wel daadwerkelijk van Google kwamen door een reverse DNS Lookup te doen op de diverse IP-adressen. Google publiceert niet met welke IP-adressen zij websites bezoeken en zodoende geeft enkel een reverse dns lookup zekerheid dat het Googlebot is. Uit deze lookups bleek inderdaad dat het Googlebot was. Instinctief zijn we daarom gelijk naar de Google Search Console gegaan om te analyseren of hier wat opvallends was te zien.

En dat was zeker het geval. We zagen onderstaande grafiek, oftewel Google was zijn crawlbudget langzaam blijven vergroten tot een duizelingwekkend van 947.000 crawlacties per dag (oftewel 10 per seconde) en meer dan 25 Gigabyte bandbreedte per dag.

De crawlstatistieken uit Search Console: gecrawlde pagina's
De crawlstatistieken uit Search Console: gedownloade kilobytes

Eind september 2017 was de website live gegaan en na een kleine ‘herindexeringspiek’ crawlde Google zo’n 400 pagina’s per dag. Sinds half november begon Google echter dag na dag meer te indexeren tot deze duizelingwekkende aantallen.

Als eerste noodoplossing werd besloten om per direct de crawlsnelheid in Google Search Console te verlagen tot het absolute minimum.

De crawlstatistieken uit Search Console: gecrawlde pagina's

Dit had bijna direct gevolgen en Google hield zich netjes aan de crawlsnelheid. Echter het probleem was niet voorbij, aangezien 1 request per seconde nog steeds betekent dat er 86.400 requests per dag werden gedaan en dit was ook bijna exact het aantal dat we de volgende dagen voorbij zagen komen.

Het probleem was nog niet opgelost aangezien de website ongeveer 400 pagina’s bevat en dat dus ook ongeveer het aantal gecrawlde aantal pagina’s per dag zou moeten zijn.

De aangevallen pagina

Al snel zagen we dat vooral de overzichtspagina met een lijst met producten werd ‘aangevallen’. De pagina had drie opties om de resultaten te filteren; op basis van de categorie, de designer van het product en het model van het product.

Een relatieve standaardfunctionaliteit om resultaten te filteren, die we op vele van onze website hebben gecreeerd en eigenlijk niets opvallends bevat. Het is daarnaast mogelijk om per type filtering meerdere filters toe te voegen.

Bij een nadere inspectie van de html viel echter wel wat vreemds op. Er was door een collega namelijk gekozen om de dropdownlists met filtering niet op te maken met een standaard HTML-element voor dropdownlist [select][option][/option][select]. Er bleek gekozen te zijn voor een verborgen element op de pagina met daarin allemaal linkjes [div][a href][/a][a href][/a][/div].

De filtering op de overzichtspagina

Als er vervolgens op een filtering werd geklikt, dan werd deze filtering opgenomen in de querystring en ontstond er een nieuwe url. Doordat er meerdere filters toegepast werden, werd het aantal unieke url’s schier oneindig (Een benadering van het aantal combinaties is: 5! * 10! * 53!, oftewel een 1 met 78 nullen).

De filtering nadat er al gefilterd was op de categorie "Banken"

De achterliggende reden van de programmeur om het op deze manier te implementeren was om de crawlbaarheid van de pagina zou verhogen, aangezien een [a]-element (het standaard HTML-element voor een link) makkelijker te volgen is dan het onchange-event van een dropdownelement welke met javascript werkt. En dat het de crawlbaarheid vermakkelijkt merkten we!

De kracht van Twitter

We weten dat crawlen eigenlijk niets anders is dan het ophalen van data van een website en de links hier volgen, maar stiekem hadden we toch de verwachting dat Google dit soort extreme uitwassen zou voorkomen in haar spidering. Omdat we ons bijna niet konden voorstellen dat er zo weinig logica in de crawling van de Googlebot zou zitten, werd uitgeweken naar Twitter om te kijken of we misschien advies zouden kunnen krijgen van John Mu van Google. Binnen enkele uren hadden we de bevestiging dat dat het inderdaad te maken had met de filtering en de navigatie en dat we verder moesten duiken in “faceted navigation” en het feit dat we een oneindig aantal combinaties van filtering aanboden.

Faceted search

Om dit probleem te tackelen kwam we twee oplossingen tegen:

  • een “nofollow” op de links zetten waarvan je niet wilde dat Google ze zou vinden, of
  • een uitsluiting van bepaalde querystringparameters in de robots.txt

Omdat we op dit moment al zo gefascineerd waren door deze situatie besloten we ze allebei onafhankelijk van elkaar uit te proberen.

Oplossing 1: Rel=“nofollow” toevoegen op alle linkjes

De theorie zegt dat als je een nofollow toevoegt aan een linkje Google deze link niet volgt en daardoor niet al deze aantallen zouden worden geïndexeerd. De oplossing was binnen enkele minuten geïmplementeerd en binnen een dag zagen we een duidelijk verschil. De Googlebot luisterde zelfs zo goed dat we de crawlsnelheid weer op automatisch konden zetten. Probleem opgelost zou je zeggen!

Echter op dat moment kwamen we er achter dat er veel meer bots al onze websites bezoekten en dat die lang niet zo slim waren als de Googlebot en simpelweg niet luisterde naar de nofollow-instructies. Weliswaar hadden we de crawlsnelheid van Google getempert, maar andere bots gingen onverhoopt door en zorgden ook voor vele ‘onnodige’ paginaaanroepen. Het enige waar (bijna al) deze bots naar luisterden was een uitsluiting doormiddel van een robots.txt.

Oplossing 2: De robots.txt-oplossing

Het alternatief was om in de robots.txt aan te geven welke url’s niet geïndexeerd mochten worden. Als eerste draaide we oplossing 1 terug om een zo zuiver mogelijk resultaat te krijgen en implementeerde we daarna pas oplossing 2. Vooraf stonden waren er geen specifieke bots of url’s uitgesloten, maar door middel van een reguliere expressie zouden we de drie filter-querystring uitsluiten:

  • # Block specific querystring parameters
  • User-agent: *
  • Disallow: *categorie=*
  • Disallow: *ontwerper=*
  • Disallow: *model=*

En binnen één tot drie dagen hadden alle bots deze nieuwe robots.txt gezien en was de DDOS-aanval eindelijk voorbij.

Conclusie

Inmiddels zijn het aantal crawlacties op de website gelukkig genormaliseerd door bovenstaande oplossing in te zetten. Het is opvallend om te zien dat er in de Googlebot nog geen intelligentie zit om een oneindig aantal url’s op basis van querystrings zelf te herkennen en niet te blijven volgen. Daarnaast hebben we ook geleerd dat het ‘nofollow’-attribuut door Googlebot wordt gerespecteerd, maar door alle andere spiders en zoekmachines niet. De veel betere oplossing is daarom om het via robots.txt te doen. Een laatste opvallendheid is dat Twitter voor expert-advies nog altijd een uitstekend medium is om te gebruiken.