.. title: systemd-service zum Zählen von Zugriffen nach ASN
.. slug: systemd-service-zum-zaehlen-von-zugriffen-nach-asn
.. date: 2026-01-09 19:00:00 UTC+01:00
.. tags: Technik
.. category: 
.. link: 
.. description: 
.. type: text
.. author: Masin Wiedner
.. mastodon: 115866456137100084

.. admonition:: Update

    Ich habe Fehler bereinigt. Siehe den `neuen Blogbeitrag`_ dazu.

.. admonition:: Serie

    * Teil 1: systemd-service zum Zählen von Zugriffen nach ASN (dieser Artikel)
    * Teil 2: `systemd asncounter-service <neuen Blogbeitrag_>`_

Ich will es wissen: Woher kommen die Zugriffe auf meinen Rootserver? Und stellt das ein Problem dar?

Die letzte Frage kann ich klar mit "nein" beantworten. Der Server langweilt sich die meiste Zeit. Aber neben meinem Rootserver habe ich noch einen virtuellen Server (VPS, virtual private server), der ein bisschen mehr zu tun hat und bei dem es ein Problem sein könnte, wenn da zu viel Mist aufläuft. Der Rootserver ist aber ein gutes Versuchskaninchen.

Anarcat hat letztes Jahr das |Python-Programm asncounter veröffentlicht|_, das Logs aus verschiedenen Quellen nehmen kann, um sie zu analysieren und eine ASN-Statistik auszugeben. Im (englischsprachigen, aber gut verständlichen) Blogbeitrag_ befinden sich Erklärungen zu AS, ASN und BGP.

Der Server läuft derzeit noch mit Debian 12. Anarcat stellt in Aussicht, dass ``asncounter`` in Debian 14 in den offiziellen Repositorys enthalten seien könnte. Bis dahin ist die beste Installationsmethode wohl mittels ``pip`` bzw. ``pipx``. Ich habe mich für letzteres entschieden. Der Einfachheit halber installiere ich gleich die Pakete mit, die bei der Installation von ``asncounter`` benötigt werden::

    apt install pipx build-essential python3-dev

Ich mag es nicht, wenn ``pipx`` die virtuellen Environments und so in ``/root`` erstellt. Deswegen setze ich in der ``/root/.bashrc`` ein paar Variablen für ``pipx``::

    export PIPX_BIN_DIR=/usr/local/bin
    export PIPX_HOME=/usr/local/share/pipx
    eval "$(register-python-argcomplete pipx)"

Die letzte Zeile dient der Tabvervollständigung von ``pipx``-Befehlen. Einmal kurz ausgeloggt und wieder eingeloggt, geht es weiter::

    pipx install --include-deps asncounter

Das installiert den ``asncounter`` inklusive seiner Abhängigkeiten. Der Blogbeitrag erwähnt im tl;dr am Anfang eine Befehlszeile folgenden Formats::

    tcpdump -q -i enp0s31f6 -n -Q in "tcp and tcp[tcpflags] & tcp-syn != 0 and (port 80 or port 443)" | asncounter --input-format=tcpdump --repl

Ich lese "``tcpdump``" jetzt nicht so wahnsinnig flüssig, aber ich erkenne eine Filterung nach TCP-Zugriffen auf Ports 80 und 443. Das soll mir für den Anfang reichen. Dummerweise hänge ich dann im REPL fest und muss `die dazugehörige man-Page`_ erstmal ein wenig gründlicher lesen, wo ich auf ``recorder.display_results()`` stoße::

    >>> recorder.display_results()
    count	percent	ASN	AS
    7248	85.27	265269	MEGA TELE INFORMATICA, BR
    1132	13.32	270606	R3 TELECOM, BR
    25	0.29	54801	ZILLION-NETWORK, US
    25	0.29	45102	ALIBABA-CN-NET Alibaba US Technology Co., Ltd., CN
    15	0.18	209334	MODAT-01, NL
    11	0.13	197540	NETCUP-AS netcup GmbH, DE
    6	0.07	16276	OVH, FR
    4	0.05	213438	COLOCATEL-INC Colocatel Network - High Bandwidth Dedicated Servers, SC
    4	0.05	14061	DIGITALOCEAN-ASN, US
    3	0.04	211607	RECORDEDFUTURE, US
    unique ASN: 26
    count	percent	prefix	ASN	AS
    1826	21.48	168.90.91.0/24	265269	MEGA TELE INFORMATICA, BR
    1823	21.45	168.90.89.0/24	265269	MEGA TELE INFORMATICA, BR
    1806	21.25	168.90.88.0/23	265269	MEGA TELE INFORMATICA, BR
    1793	21.09	168.90.90.0/24	265269	MEGA TELE INFORMATICA, BR
    310	3.65	177.37.19.0/24	270606	R3 TELECOM, BR
    282	3.32	177.37.17.0/24	270606	R3 TELECOM, BR
    273	3.21	177.37.18.0/24	270606	R3 TELECOM, BR
    267	3.14	177.37.16.0/24	270606	R3 TELECOM, BR
    25	0.29	148.178.64.0/20	54801	ZILLION-NETWORK, US
    25	0.29	47.83.0.0/17	45102	ALIBABA-CN-NET Alibaba US Technology Co., Ltd., CN
    unique prefixes: 34
    total lookups: 8500
    total skipped: 0
    total failed: 0

``asncounter`` gibt also im Falle des Durchpipens von ``tcpdump`` nur auf explizite Anfrage Werte aus. Damit kann man sicher arbeiten, aber mir wird beim Gedanken, irgendwelche Sockets regelmäßig abzufragen, ein wenig flau im Magen. Langlaufende Prozesse, die ich verbrochen habe? Nein, danke :-).

Aber ``tcpdump`` minütlich Dinge erfassen lassen, die ich ``asncounter`` dann zum Analysieren vorwerfen kann? Klar, das sicher. Und so lernte ich heute von ``timeout``, das genau das tut, was ich will::

    timeout -sHUP 1m tcpdump -q -i enp0s31f6 -n -Q in "tcp and tcp[tcpflags] & tcp-syn != 0 and (port 80 or port 443)" > tcpdump4asncounter.log

Jetzt brauche ich nur ein Bash-Skript, das mir jede Minute eine Datei mit diesen Daten erstellt.

::

    #!/usr/bin/env bash
    CACHE_DIR=/var/cache/count_asn
    IF="${INTERFACE:-any}"
    DIR="${CACHE_DIRECTORY:-${CACHE_DIR}}"
    printf "Interface set to %s.\n" "${IF}"
    printf "Cache directory set to %s.\n" "${DIR}"

    cleanup () {
    	#kill -s SIGTERM $!
    	exit 0
    }

    trap cleanup SIGINT SIGTERM

    if [ ! -d "${DIR}" ]
    then
    	install -d "${DIR}"
    fi

    printf "Starting logging loop …\n"
    while true
    do
    	CURRENT=$(date +%s)
    	timeout -sHUP 10s tcpdump -q -i "${IF}" -n -Q in "tcp and tcp[tcpflags] & tcp-syn != 0 and (port 80 or port 443)" > "/tmp/count_asn_${CURRENT}.log" 2> /dev/null
    	find "${DIR}" -type f -mtime +1 -delete
    	mv "/tmp/count_asn_${CURRENT}.log" "${DIR}/"
    	cat "${DIR}/"count_asn_*.log | /usr/local/bin/asncounter --input-format tcpdump --no-prefixes --output /etc/motd.d/01-asncounter.txt 2> /dev/null
    done

Am Anfang werden ein paar Variablen initialisiert, die ich entweder per ``systemd`` übergebe oder eben auch nicht. Dann braucht es aber sinnvolle Defaults.

Ich habe feststellen dürfen, dass sich so eine ``while-true``-Schleife nicht mit Strg+c abbrechen lässt. Vielleicht liegt es auch an ``timeout``. Deswegen werden die Signale ``SIGINT`` und ``SIGTERM`` explizit abgefangen und in der ``cleanup()``-Funktion behandelt. Das aktuelle ``tcpdump`` läuft aber noch bis zum Ende durch. Damit kann ich leben.

Der Dump wird erstmal nur nach `/tmp` geschrieben. Dann werden die Dateien entfernt, die älter als 1 Tag sind, bevor die neue Datei in den Cache geschoben wird. Der Cache-Inhalt wird dann ``asncounter`` zur Analyse übergeben, das Ergebnis wird nach ``/etc/motd.d`` geschrieben (Verzeichnis muss manuell erstellt werden). Und auf diese Weise lernte ich, dass ``pam_login`` auch die Dateien dieses Verzeichnisses ausgibt statt nur ``/etc/motd``.

Natürlich muss das Skript ausführbar gemacht werden::

    chmod +x /usr/local/bin/count_asn

Jetzt muss das Skript nur noch dauerhaft laufen. Ich benutze dafür gerne ``systemd``. Schnell mal eine Vorlage im Web herausgesucht und an meine Bedürfnisse angepasst. Ich bin leider immer noch nicht so weit, dass ich das aus dem Ärmel schütteln kann::

    # /etc/systemd/system/count_asn.service
    [Unit]
    Description=Count ASNs using asncounter and update motd
    After=network.target

    [Service]
    Type=simple
    Environment=INTERFACE=enp0s31f6
    ExecStart=/usr/local/bin/count_asn
    Restart=always
    RestartSec=5
    CacheDirectory=count_asn
    IgnoreSIGPIPE=no

    [Install]
    WantedBy=multi-user.target

Der ``Install``-Abschnitt gibt wie immer an, an welcher Stelle beim Booten der Dienst gestartet werden soll, wenn er enabled wird. Im ``Unit``-Abschnitt sagen wir an, dass der Dienst erst nach dem Erreichen des ``network.target`` gestartet werden soll. Verfügbarkeit von Netzwerk ist eine Wissenschaft für sich, aber hier sollte das passen.

Der wichtigste Teil ist hier ``IgnoreSIGPIPE=no``, ansonsten klappt das Pipen der Daten an ``asncounter`` nicht. Das Skript kriegt mit der Umgebungsvariable ``INTERFACE`` noch die richtige Schnittstelle mitgeteilt.

Lohn der Mühe::

    $ ssh root@hades
    Linux hades.fluchtkapsel.de 6.1.0-41-amd64 #1 SMP PREEMPT_DYNAMIC Debian 6.1.158-1 (2025-11-09) x86_64

    The programs included with the Debian GNU/Linux system are free software;
    the exact distribution terms for each program are described in the
    individual files in /usr/share/doc/*/copyright.

    Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
    permitted by applicable law.
    count	percent	ASN	AS
    21811	78.65	265269	MEGA TELE INFORMATICA, BR
    5486	19.78	265410	JL INFORMATICA E TELECOM LTDA - ME, BR
    108	0.39	14618	AMAZON-AES, US
    71	0.26	197540	NETCUP-AS netcup GmbH, DE
    43	0.16	8075	MICROSOFT-CORP-MSN-AS-BLOCK, US
    40	0.14	202306	HOSTGLOBALPLUS-AS, GB
    31	0.11	51852	PLI-AS, PA
    17	0.06	206264	AMARUTU-TECHNOLOGY, SC
    14	0.05	398705	CENSYS-ARIN-02, US
    10	0.04	62068	SPECTRAIP SpectraIP B.V., NL
    unique ASN: 40
    total lookups: 27730
    total skipped: 152
    total failed: 0
    Last login: Fri Jan  9 18:05:35 2026 from 79.248.89.181

Ich werde beim Login mit der Statistik begrüßt. Das sieht mir jetzt robust genug aus, dass ich das auch auf meinem VPS einrichten kann. Dort läuft Arch Linux. Als erstes installiere ich ``pipx``::

    pacman -Sy python-pipx python-pip base-devel

``python-pip`` ist nur dafür dabei, falls ich mal manuell in die venv schauen muss, und ``base-devel`` ist das Arch-Äquivalent zu Debians ``build-essential``. Als nächstes kommen die Einträge in die .bashrc von oben gefolgt von einem Logout und erneuten Login.

Ich übertrage das Skript und den Service, passe die Schnittstelle an, erstelle das Verzeichnis ``/etc/motd.d`` und starte den Service. Nach ein paar Minuten gibt es dann auch hier Statistiken::

    $ ssh root@persephone
    count	percent	ASN	AS
    651	58.97	265269	MEGA TELE INFORMATICA, BR
    151	13.68	265410	JL INFORMATICA E TELECOM LTDA - ME, BR
    113	10.24	24940	HETZNER-AS, DE
    61	5.53	14618	AMAZON-AES, US
    22	1.99	16276	OVH, FR
    12	1.09	197540	NETCUP-AS netcup GmbH, DE
    8	0.72	3320	DTAG Internet service provider operations, DE
    8	0.72	63949	AKAMAI-LINODE-AP Akamai Connected Cloud, SG
    8	0.72	15169	GOOGLE, US
    7	0.63	14061	DIGITALOCEAN-ASN, US
    unique ASN: 52
    total lookups: 1104
    total skipped: 7
    total failed: 9462

Deutlich weniger Betrieb. Das überrascht. Im nächsten Schritt muss ich dann mal schauen, ob ich aus diesen Daten sinnvolle Regeln für die Firewall ableiten kann. Auf beiden Systemen läuft ``nftables`` – das macht es mir ein wenig einfacher. Aber das ist eine Aufgabe für einen Folge-Eintrag ins Blog.

Dieser Blog-Eintrag wurde ohne Unterstützung generativer KI erstellt.


.. |Python-Programm asncounter veröffentlicht| replace:: Python-Programm ``asncounter`` veröffentlicht
.. _Python-Programm asncounter veröffentlicht: https://gitlab.com/anarcat/asncounter
.. _die dazugehörige man-Page: https://gitlab.com/anarcat/asncounter/-/blob/main/asncounter.1.md
.. _Blogbeitrag: https://anarc.at/blog/2025-05-30-asncounter/
.. _neuen Blogbeitrag: /posts/systemd-asncounter-service