Blog der Heimetli Software AG

Wie beeinflusst die Corona-Krise die Zugriffszahlen?

Dieser Post dokumentiert die Analyse der Apache-Logs, damit ich sie später wieder reproduzieren kann. Die Analyse lief Ad-Hoc ab, es gibt deshalb kein fertiges Script das eine wunderbare Auswertung erstellt.

Das Ergebnis der Auswertung

Bei blog.heimetli.ch kann ich keinen Einfluss erkennen:

Zugriffe auf blog.heimetli.ch

Bei www.heimetli.ch gab es eine leichte Abschwächung, aber die Veränderung ist minimal.

Was mich bei diesen Analysen immer wieder erstaunt: der Wochentag hat anscheinend überhaupt keinen Einfluss auf die Besucherzahl. Das ist nicht nur diesmal so sondern jedesmal wenn ich wieder einen Anlauf nehme.

1. Schritt: Filterung der Logzeilen

Wenn man es nicht selber gesehen hat, glaubt man kaum wie viele Bots, Spider, und Crawler auf einer Website herumturnen.

Errors

Wie bereits in Attacken auf www.heimetli.ch gezeigt, gibt es viele sinnlose Zugriffe von Scripts die einen Angriffspunkt auf der Website suchen. Die werden alle ausgefiltert durch einen Check des Resultcodes auf 4xx.

Bots, Spiders und Crawlers

Schon ein grep -i bot listete Dutzende von Bots auf. Und das sind selbstverständlich nur die seriösen Bots die sich zu erkennen geben!

Es zeigte sich dabei dass einzelne Bots mehrere Varianten von Gross- und Kleinschreibung verwenden. Aus diesem Grunde werden die Log-Zeilen und Bot-Kennungen im Script systematisch in Kleinschreibung konvertiert.

Einige Bots bezeichnen sich selber auch gleich als Spider, so dass die Liste der reinen Spider recht kurz geworden ist.

Crawler gibt es ebenfalls nicht so viele, aber auch die machen viele Zugriffe auf meine Seiten.

Schlussendlich kamen ein paar Clients auf die Liste die viele Zugriffe machten, aber nicht zu klassifizieren waren.

Filterung von IP-Adressen

Immer wieder tauchten Spitzen im Diagramm auf die von mehr oder weniger gezielten Zugriffen von Clients stammen die nicht zu identifizieren sind. Deshalb wird auch noch nach IP-Adressen gefiltert.

Fertig?

Sicher nicht, aber irgendwann wird die Suche nach weiteren Störfaktoren zu mühsam. Die gröberen Sörfaktoren dürften aber eliminiert sein.

Lästig sind die Zugriffe von Google-Apps-Script. Auch nach längerer Google-Suche fand ich niemanden mit einer ähnlichen Meldung. Selbstverständlich ähnelt das Meldesystem bei Google einer mittelalterlichen Burg, wo man nur unter grössten Anstrengungen eine Nachricht abgeben kann.

Weil sonst anscheinend nichts zu machen ist, habe ich Adressbereiche mit 107.178.x.x durch iptables vom Server ausgesperrt...

Python-Code zur Filterung

import re

# List of the user agents to filter
bots = [
 # Bots
 "ahrefsbot",
 "alphabot",
 "alphaseobot",
 "applebot",
 "aspiegelbot",
 "bingbot",
 "blexbot",
 "bot@linkfluence",
 "bot@tracemyfile",
 "brands-bot",
 "ccbot",
 "clarabot",
 "cliqzbot",
 "coccocbot",
 "discordbot",
 "domainstatsbot",
 "dotbot",
 "duckduckbot",
 "duckduckbot",
 "exabot",
 "twitterbot",
 "googlebot",
 "internet-structure-research-project-bot",
 "jobboersebot",
 "kazbtbot",
 "keybot",
 "mj12bot",
 "msnbot",
 "nimbostratus-bot",
 "obot",
 "our-bot",
 "adbeat_bot",
 "ru_bot",
 "semrushbot",
 "seobilitybot",
 "serpstatbot",
 "seznambot",
 "sidetrade indexer bot",
 "smtbot",
 "statvoobot",
 "surdotlybot",
 "tigerbot",
 "tmmbot",
 "vebidoobot",
 "x28-job-bot",
 "yacybot",
 "yandexbot",
 "zoominfobot",
 # Spiders
 "spider@seocompany.store",
 # Crawlers
 "barkrowler",
 "website-datenbank.de",
 "crawler_eb_germany",
 "searchatlas.com",
 "adstxtcrawler",
 "publicwebcrawler",
 # Unknown 
 "sslyze",
 "localsearch",
 "winhttprequest" ]

# Unidentified IP addresses with suspicious access patterns
ips = ["212.227.250.21","82.80.2","95.217.74.38","146.4.22.190"]

pattern = re.compile( "\" 40[0-9] " )

# Read the log file
with open("access.log","r") as log:
    for line in log:
        # Discard inexplicable hits
        if not any( line.startswith(ip) for ip in ips ):
            # Discard the errors
            if not re.search(pattern,line):
                # Discard the bots
                str = line.lower()
                if not any( bot in str for bot in bots ):
                    print( line.strip() )

2. Zugriffe pro Tag zusammenzählen

Selbstverständlich könnte man das auch gleich im Python-Script machen, aber ich habe mich für eine Pipeline entschieden:

(echo "count date";python3 logfilter.py | awk -F '[][]' '!/fake-data/ { print substr($2,0,12) }' | uniq -c) > log.data

fake-data ist ein Script welches Daten für einen Chart liefert. Es gibt viele Zugriffe darauf, aber die haben in diesem Kontext nichts zu bedeuten.

3. Resultat als Graph darstellen

Für die Analyse brauchte ich nur ein einfaches Script um die Daten rasch interpretieren zu können:

import pandas as pd
import matplotlib.pyplot as plt

df = pd.read_csv( "log.data", delim_whitespace = True )

print( df.describe() )

df.plot( kind="bar", y="count" )
plt.show()

Sehr nützlich ist dabei die Ausgabe von describe(). Minimum, Maximum und Quartile werden berechnet und angezeigt.

Die zweite Spalte wird von read_csv übrigens nicht erkannt. Die nimmt es erst zur Kenntnis wenn das File in ein echtes CSV konvertiert wird.

Eine Version mit Plotly gibt es jetzt auch.