ReportedIP-Agent für Linux
Der Agent ist eine einzelne statische Binärdatei und erledigt auf einem Linux-Server zwei Aufgaben: Er hält die Community Blacklist in der Kernel-Firewall aktuell und meldet die Angreifer, die er in den Logs dieses Servers findet. Auf Wunsch blockiert er diese lokalen Funde auch selbst. Er ersetzt das handgeschriebene Sync-Skript aus dieser Dokumentation und übernimmt die Arbeit, die bisher fail2ban gemacht hat.
linux/amd64 und linux/arm64. Jeder Server braucht eine Lizenz, eine ist
in Professional und drei sind in Business enthalten, siehe
Serverlizenzen. Lizenzen werden unter Agent Servers in
Ihrem Konto hinzugefügt und
entfernt.
Funktionsweise
Community Blacklist in den Kernel
Fünf Listen, eine pro exponiertem Dienst (ssh, mail, web, ftp, edge), so oft abgerufen, wie Ihr Tarif es erlaubt, und atomar in ein ipset oder ein nftables-Set getauscht. Eine Liste, die leer oder unplausibel kurz zurückkam, wird nie übernommen. Ein fehlgeschlagener Abruf lässt also das vorherige Set stehen, statt die Tür zu öffnen.
Lokale Angriffe erkannt und gemeldet
Der Agent liest die Logs mit, die der Server sowieso schreibt, zählt Treffer pro Adresse gegen einen Schwellwert, der zu dieser Quelle gehört, und meldet die Adresse, sobald der Schwellwert erreicht ist. Keine Logzeile, kein Benutzername und keine URL verlässt dabei die Maschine.
Lokale Funde blockiert, wenn Sie das wollen
Nach der Installation aus. Eingeschaltet landet eine Adresse, die der Agent selbst erwischt hat, in einem Kernel-Set mit Timeout, und ein Wiederholungstäter wird jedes Mal länger gesperrt.
Voraussetzungen
Vier Dinge, und nur das letzte muss von uns kommen.
- Ein Linux-Kernel mit einem beschreibbaren Paketfilter. Entweder
ipsetzusammen mitiptablesodernftables. Auf einem Debian- oder Ubuntu-Host ist dasapt install ipset iptablesbeziehungsweiseapt install nftables, in der RHEL-Familiednf install ipset iptablesoderdnf install nftables. Der Agent nutzt auchip6tables, wenn es da ist; ohne das Werkzeug werden IPv6-Sperren erfasst, aber nicht durchgesetzt. - systemd für den Timer und den Watch-Dienst. Auf einem Host ohne systemd läuft der Agent trotzdem, mit dem Sync aus der Crontab und dem Watcher aus Ihrem eigenen Init-System. Der Abschnitt weiter unten beschreibt das.
- Root. Der Agent schreibt Firewall-Regeln und liest Logs, die nicht für alle lesbar sind, und beides braucht Root. Es gibt keinen abgespeckten Modus für einen normalen Benutzer.
- Einen API-Key aus Ihrem Konto. Der Key wird bei der Installation zweimal gebraucht, einmal für den lizenzierten Download und einmal, um den Host zu registrieren. Ein Key pro Host ist die Empfehlung; mehrere Hosts an einem Key sind erlaubt und kosten nichts extra, denn ein Host wird über seine Install-ID erkannt und nicht über den Key.
Mehr nicht. Die Binärdatei ist statisch gelinkt und ohne cgo gebaut, bringt also keinen Interpreter,
keine Bibliothek, kein Paketrepository und keinen eigenen Cron-Helfer mit. Für den Download und die
Prüfsumme braucht install.sh noch curl oder wget sowie
sha256sum, und ohne das Prüfwerkzeug installiert es nichts. Entwickelt und gemessen
wurde der Agent auf Debian 12 (bookworm) auf arm64 mit ISPConfig, nginx, Postfix, pure-ftpd und
bind.
ipset oder nftables, und was auto entscheidet
Beide Backends machen dieselbe Arbeit, und auf einem frischen Host ist keines besser. Entscheidend ist, was der Host schon benutzt, denn zwei Paketfilter, die dieselbe INPUT-Kette beschreiben, sind die Art, wie ein Nachmittag verschwindet.
backend | Was passiert |
|---|---|
auto (Standard) | ipset wird bevorzugt, wenn ipset und iptables beide vorhanden sind, sonst wird nft genutzt. Die Vorliebe gibt es, weil CSF und der veröffentlichte Firewall-Guide diese Werkzeugkette verwenden; ein Host mit bestehenden Regeln behält sie so. |
ipset | Sets in ipset, Regeln in der Kette rip-blacklist von iptables und ip6tables. Fehlt eines der Werkzeuge, bricht der Agent mit klarer Meldung ab statt zurückzufallen. |
nftables | Sets und Regeln in der eigenen Tabelle inet reportedip. Bricht ab, wenn nft fehlt. |
Eine Versionsabfrage entscheidet das nie. Es zählt nur eine Binärdatei, die es wirklich gibt, denn
iptables --version antwortet auf einem Host mit nft-Backend etwas, das richtig aussieht
und nichts bedeutet. Nach dem ersten Sync ist das gewählte Backend festgehalten, und ein späterer
Wechsel braucht reportedip-agent sync --migrate-backend, statt still einen zweiten Satz
Regeln aufzubauen.
Zuerst den Host prüfen
doctor ist der Befehl, den Sie vor der Installation ausführen. Er ändert gar
nichts: keine Datei, kein Verzeichnis, keine Regel, kein Set. Alles, was er berichtet, hat er
gelesen.
reportedip-agent doctor
Er beantwortet sechs Fragen, in dieser Reihenfolge:
- system: die Distribution, so wie ihre eigene
os-releasesie nennt, den Kernel, die Plattform, ob systemd wirklich läuft (gelesen aus/run/systemd/system, nicht daran erkannt, dasssystemctlexistiert), die Zeitzone, in der Logs ohne Zeitzonenangabe gelesen werden, und den freien Platz dort, wo das Statusverzeichnis liegen wird. - ssh: welche Unit den sshd betreibt, und den Port. Interessant ist der Fall
ssh.socket: mit Socket-Aktivierung antwortetsshd -Tweiterhin 22, während der echte Port in der Socket-Unit steht. Der Port kommt dann aus dem lauschenden Prozess. doctor sagt, welcher der beiden Wege gegriffen hat, denn wer einen falschen Port in der Config sieht, schaut zuerst hier nach. - firewall: wo
ipset,iptables,ip6tablesundnftliegen, welches Backend daraus folgt, und ob das lokale Bann-Set ein Timeout pro Eintrag trägt. Der letzte Punkt entscheidet, ob der Kernel eine Sperre selbst abläuft, und genau das verhindert, dass ein abgestürzter Agent eine dauerhafte Sperre hinterlässt. - panel: ISPConfig, Plesk, cPanel oder DirectAdmin. Nur das Log-Layout von ISPConfig kennt diese Version. Die anderen werden benannt statt geraten, denn ein falscher Glob würde den Agenten Byte-Zähler lesen lassen statt Access-Logs.
- sources: jede konfigurierte Quelle, aufgelöst auf echte Dateien, mit der Anzahl und der Anzahl der lesbaren darunter, der größten Datei samt geschätzter Zeilenzahl und einem Hinweis auf Dateien, die es gibt und die leer sind. Auf dem größten gemessenen Panel-Host löst der Web-Glob auf 196 Dateien auf, und wer den Agenten dort installiert, sollte das vorher wissen und nicht hinterher.
- mail: ob eine Meldung diesen Host überhaupt verlassen könnte. Von achtzehn
gemessenen Hosts konnten vierzehn Mail ausliefern, zwei hatten
sendmailbei gestopptem MTA, und zwei hatten gar keinen MTA. Ohne diesen Abschnitt wartet jemand auf eine Mail, die nie kommt.
Das Urteil lesen
Der letzte Block heißt verdict und entspricht dem Exit-Code, eine Monitoring-Prüfung
muss also keine Ausgabe parsen.
| Exit | Urteil | Bedeutung |
|---|---|---|
0 | alles da, was der Agent braucht | Installieren. |
1 | läuft auf diesem Host, mit den genannten Einschränkungen | Jede Einschränkung steht namentlich in der Ausgabe. Ein fehlendes Firewall-Backend heißt, dieser Host meldet und blockt nicht, und das ist eine gültige Installation. Eine Quelle, die auf nichts auflöst, sollte man vorher beheben. |
2 | kann auf diesem Host nicht laufen | Kein Linux-Host, oder ein Host, der weder blocken noch ein einziges Log lesen kann. Ursache vor der Installation beheben. |
Führen Sie doctor nach der Installation noch einmal aus. Mit einer Config rät er nicht
mehr, sondern berichtet die konfigurierten statt der erkannten Quellen, und er ergänzt die
Uhrenabweichung pro Quelle, die der Daemon gemessen hat. Eine Quelle, deren Log jede Zeile mehr als
eine Minute von der Systemuhr entfernt stempelt, hat ein Zählfenster, das sich nie füllt, und das ist
der eine Fehler, der genau wie „der Detektor funktioniert nicht" aussieht.
Installation
Ein Befehl, als root. Er liest die aktuelle Version aus den öffentlichen Metadaten, lädt mit Ihrem
Key den Build für Ihre Architektur, prüft ihn gegen SHA256SUMS, installiert ihn nach
/usr/local/bin/reportedip-agent und richtet danach den Host ein.
curl -fsSL https://reportedip.com/agent/install.sh | REPORTEDIP_KEY=<YOUR-KEY> sh
Der Key steht in der Umgebung, weil er zweimal gebraucht wird, einmal für den lizenzierten Download
und einmal für die Registrierung des Hosts, und zweimal einfügen ist die Art, wie ein Key in falscher
Form in einer Shell-History landet. Das Skript ist bewusst POSIX-sh: es muss auf Hosts
laufen, auf denen bash nicht die Standard-Shell ist. Es bricht mit genanntem Grund und ohne
Installation ab, wenn es nicht als root läuft, wenn der Key fehlt, wenn die Plattform nicht Linux
ist, wenn die Architektur weder amd64 noch arm64 ist, wenn weder curl noch
wget existiert und wenn sha256sum fehlt.
Die beiden Abrufwege sind absichtlich getrennt. Die Versions-Metadaten werden ohne Key geholt, die lizenzierten Dateien mit Key, damit der Key nie an ein Umleitungsziel geht, das nur öffentliche Metadaten ausliefert. Aus der Prüfsummendatei wird nur die Zeile Ihrer eigenen Architektur geprüft, denn die Datei listet auch die andere.
Was der Installer wirklich tut
Alles hier ist idempotent. Derselbe Befehl auf einem Host, der den Agenten schon hat, aktualisiert die Binärdatei und lässt die Konfiguration genau so, wie sie war.
- Liest
https://reportedip.com/agent/latestohne Key und holt die Version daraus. Diese Datei ist dasselbe JSON, das der Agent selbst für Updates abfragt. - Lädt
reportedip-agent_linux_<arch>undSHA256SUMSmit dem HeaderX-Keyin ein temporäres Verzeichnis, das auf jedem Ausgangspfad gelöscht wird. - Prüft die Prüfsumme und installiert bei einer Abweichung nichts.
- Installiert die Binärdatei mit Modus 0755 nach
/usr/local/bin/reportedip-agentund gibt die gerade abgelegte Version aus. - Startet
reportedip-agent.serviceneu, wenn diese Unit gerade aktiv ist. Das ist bei einem Upgrade wichtig: der Watch-Daemon würde sonst bis zum nächsten Reboot den alten Code weiterlaufen lassen. Die Sync-Unit ist ein Oneshot und nimmt die neue Binärdatei beim nächsten Start von allein. - Führt die Host-Einrichtung aus, es sei denn,
REPORTEDIP_NO_SETUP=1ist gesetzt oder/etc/reportedip-agent/config.yamlexistiert schon. Im zweiten Fall sagt er das und lässt die Konfiguration in Ruhe.
Die Host-Einrichtung ist der Schritt, der Dateien schreibt, und sie ist dasselbe wie
reportedip-agent install --key. Der Reihe nach:
- Legt
/etc/reportedip-agentund/var/lib/reportedip-agentan, das zweite mit Modus 0700, und korrigiert den Modus eines Verzeichnisses, das schon da war. - Erkennt den SSH-Port aus
sshd -T, ausSSH_CONNECTIONund aus den lauschenden sshd-Prozessen und nimmt die Vereinigung der drei. Findet er nichts, bricht er ab und fragt nach--ssh-port, statt 22 anzunehmen. - Entscheidet, welche der fünf Feed-Listen konfiguriert werden.
sshundedgesind immer an.mail,webundftpkommen dazu, wenn eine passende Unit aktiv ist oder ein passender Port lauscht. Ein Host ohne Webserver bekommt also keine Web-Liste. - Erkennt die Log-Quellen und schreibt sie ausdrücklich in die Config. Erkannt wird einmal, zur Installationszeit, und das Ergebnis bleibt in der Datei: ein Dienst, der für eine Wartung gestoppt ist, darf eine Quelle nie stillschweigend abschalten.
- Schreibt
/etc/reportedip-agent/config.yamlmit Modus 0600 sowiemode: logundban.enabled: false. Eine bestehende Config wird nie überschrieben, und--keywird dann mit dem Hinweis ignoriert, stattdessenapi_keyin der Datei zu ändern. - Schreibt die Auto-Whitelist ins Statusverzeichnis: die Adresse, von der Ihre SSH-Sitzung kam, plus jede Interface-Adresse des Hosts. Die Sitzungsadresse eines früheren Laufs bleibt erhalten, damit ein zweiter Lauf aus einer anderen Sitzung nicht die Adresse entfernt, auf die der erste sich verlassen hat. Interface-Adressen werden bei jedem Lauf neu ermittelt, damit eine entfernte Adresse nicht hängen bleibt.
- Erzeugt die Install-ID, eine zufällige UUID v4 in
/var/lib/reportedip-agent/install-id. Das ist ab dann die Identität dieses Servers gegenüber der API. Der Hostname wird nie verwendet und nie übertragen. - Warnt vor zwei Dingen, die er nicht für Sie beheben kann: einer nftables-Tabelle
inet reportedip, die das dokumentierte Shell-Skript hinterlassen hat, während das aufgelöste Backend ipset ist, und einem nginx, der Cloudflare-Header liest, ohneset_real_ip_fromzu setzen. Die Web-Quelle würde dann Cloudflare-Adressen zählen statt der des Besuchers. - Schreibt die drei systemd-Units nach
/etc/systemd/system, führtdaemon-reloadaus, aktiviertreportedip-agent-sync.serviceund aktiviert und startetreportedip-agent-sync.timersowiereportedip-agent.service. - Ruft
verify-keymit der frischen Konfiguration auf und gibt Ihre Rolle und die heute verbrauchten Reports gegen das Tageslimit aus. Ein 401 oder 403 hier heißt, der Key ist falsch, und das ist der eine Fehler, der sofort behoben werden sollte.
INPUT. Das alles legt der erste reportedip-agent sync an,
und deshalb endet der Installer mit dem Hinweis, ihn auszuführen. Bis dahin ist der Host genau
so, wie er war, und eine Installation, gegen die Sie sich entscheiden, kostet ein
rm von zwei Verzeichnissen.
Die Umgebungsvariablen von install.sh
| Variable | Standard | Wofür |
|---|---|---|
REPORTEDIP_KEY | keiner, erforderlich | Ihr API-Key. Ohne ihn bricht das Skript ab, bevor es irgendetwas lädt. |
REPORTEDIP_VERSION | das aktuelle Release | Legt eine Version fest, für einen gestaffelten Rollout oder um einen bestimmten Build neu zu installieren. Alte Versionsverzeichnisse bleiben auf dem Verteilpunkt genau dafür liegen. |
REPORTEDIP_PREFIX | /usr/local/bin | Wohin die Binärdatei geht. Wenn Sie das ändern, müssen die systemd-Units folgen, denn sie nennen den absoluten Pfad. |
REPORTEDIP_BASE | https://reportedip.com/agent | Die Download-Basis. Für einen internen Spiegel, der latest, SHA256SUMS, SHA256SUMS.sig und die zwei Binärdateien ausliefert. Die Signaturprüfung gilt dort genauso. |
REPORTEDIP_NO_SETUP | nicht gesetzt | 1 legt die Binärdatei ab und hört auf. Es wird nichts erkannt, keine Config geschrieben und keine Unit installiert. Das ist die Variable für ein Golden Image, eine Container-Schicht oder einen Konfigurationsmanagement-Lauf, der die Config-Datei selbst besitzt. |
# Binary only, no host setup: for an image or for Ansible
curl -fsSL https://reportedip.com/agent/install.sh \
| REPORTEDIP_KEY=<YOUR-KEY> REPORTEDIP_NO_SETUP=1 sh
# Later, on the running host, or from your playbook:
reportedip-agent install --key "<YOUR-KEY>"
Installation von Hand
Der Einrichtungsschritt ist ein eigener Befehl und nimmt drei Flags. Führen Sie ihn aus, wenn
REPORTEDIP_NO_SETUP=1 nur die Binärdatei abgelegt hat, oder wenn die Erkennung etwas
geraten hat, das Sie korrigieren wollen.
reportedip-agent install --key "<YOUR-KEY>"
# The detection could not find the SSH port (socket activation,
# a non-standard unit, a port from an include file):
reportedip-agent install --key "<YOUR-KEY>" --ssh-port 2222
# The session address is not where you administer this host from
# (a jump host, a console, a serial connection):
reportedip-agent install --key "<YOUR-KEY>" --admin-ip 203.0.113.0/24
--admin-ip nimmt eine einzelne Adresse oder einen CIDR-Bereich und ersetzt die Vermutung
vollständig. Das lohnt sich immer dann, wenn die SSH-Sitzung nicht repräsentativ ist, denn die
geratene Adresse ist das, was am ersten Tag zwischen Ihnen und Ihrer eigenen Blockregel steht. Der
ganze Install-Lauf hat eine Frist von fünf Minuten, ein hängendes nft oder
systemctl endet also mit einem Fehler und nicht mit einem Prozess, den Sie abbrechen
müssen.
Ein Host ohne systemd
Nichts im Agenten hängt an systemd. Die Units sind eine Bequemlichkeit, und doctor sagt
das, statt abzubrechen, wenn sie nicht nutzbar sind. Zwei Dinge müssen auf so einem Host von Hand
eingerichtet werden.
# 1. The feed sync, from cron. Every 15 minutes is safe on any
# plan: the agent skips a fetch its own plan interval does
# not allow yet, so nothing is requested too often.
*/15 * * * * root /usr/local/bin/reportedip-agent sync >/dev/null 2>&1
@reboot root sleep 120 && /usr/local/bin/reportedip-agent sync
# 2. The watch daemon, from your init system. It runs in the
# foreground, logs to stderr and stops on SIGTERM.
/usr/local/bin/reportedip-agent watch
Der Eintrag für den Reboot ist nicht optional. ipset-Timeouts überleben keinen Reboot, und die Sets
selbst auch nicht, ohne einen Sync nach dem Boot kommt der Host also ohne Regeln und ohne
wiederhergestellte Sperren hoch. Auf einem systemd-Host deckt das
reportedip-agent-sync.service ab, das für multi-user.target aktiviert ist,
nach jedem Firewall-Dienst läuft und keinen Zufallsversatz hat. Lassen Sie auf einem Host ohne
journald log_file gesetzt, denn stderr führt dort möglicherweise ins Nichts.
Die erste Stunde, in der richtigen Reihenfolge
Die Reihenfolge unten ist kein Vorschlag. Jeder Schritt beantwortet eine Frage, von der der nächste abhängt, und eine andere Reihenfolge ist die Art, wie eine funktionierende Installation kaputt aussieht.
reportedip-agent doctor. Vor allem anderen, weil es der einzige Befehl ist, der nichts ändert. Was er als Einschränkung nennt, ist eine Einschränkung, die Sie sonst zwei Tage später als Symptom wiederentdecken.reportedip-agent sync. Der erste Lauf baut die Kette, legt die Sets an und lädt die fünf Listen. Das dauert einen Moment: die Listen werden nacheinander mit einer kurzen Pause dazwischen geholt.reportedip-agent status. Jetzt gibt es etwas zu sehen. Prüfen Sie, dass jede konfigurierte Liste eine plausible IPv4-Anzahl hat, dass die Ketteokmeldet, dass die Whitelist die erwarteten Adressen enthält, und dassaccountIhre Rolle und den Lizenzstatus dieses Hosts zeigt.- Die Whitelist korrigieren. Der Installer hat die Adresse Ihrer SSH-Sitzung aufgenommen. Das ist eine Vermutung. Ersetzen Sie sie durch den Bereich, von dem aus Sie tatsächlich administrieren, und tragen Sie gleich Monitoring, Backup-Host und Büro-Bereich ein.
- Warten, dann
statusnoch einmal lesen. Ein Tag reicht, zwei sind besser. Inmode: logsind die Regeln vollständig gebaut und sie greifen, sie loggen nur statt zu verwerfen. Das Kernel-Log zeigt Ihnen also genau, wasdropabgeschnitten hätte. - Auf
mode: dropwechseln undsyncausführen, denn das baut die Regeln neu. - Erst danach über
ban.enabled: truenachdenken und anschließend den Watch-Dienst neu starten. Das ist der zweite Schalter, und er betrifft Ihre eigenen Logs statt der Community-Liste.
reportedip-agent doctor
reportedip-agent sync
reportedip-agent status
reportedip-agent whitelist add 203.0.113.0/24 "management"
reportedip-agent whitelist add 198.51.100.7 "monitoring"
reportedip-agent whitelist list
mode: log, und das ist Absicht. Es wird
nichts verworfen, bis Sie es entscheiden, und das gibt Ihnen zwei Tage, um den Bereich zu
bemerken, der in der Whitelist noch fehlt. Erst Whitelist, dann drop: die umgekehrte
Reihenfolge funktioniert auch, genau bis zu dem einen Mal, an dem sie es nicht tut.
Konfiguration
Eine Datei, /etc/reportedip-agent/config.yaml, im Besitz von root und mit Modus 0600.
Der Agent startet nicht, wenn sie für Gruppe oder andere lesbar ist, und sagt das mit dem
chmod-Befehl dazu, denn in der Datei steht Ihr API-Key. Der Zustand liegt unter
/var/lib/reportedip-agent: Lesepositionen, die Report-Queue, das Dedup-Gedächtnis, der
Bann-Speicher, der Gesundheitszustand und der Update-Stand.
Die Datei, die der Installer schreibt, passt schon zum Host. Die meisten Installationen ändern in der
ersten Woche zwei Dinge, den Wert von mode und ob lokales Blocken an ist, und danach
nie mehr etwas.
window_minutes, der
leise verworfen wird, ließe Sie an einen Schwellwert glauben, den Sie nicht haben. Alle gültigen
Schlüssel stehen unten, und ein Schlüssel, der nicht in dieser Liste steht, existiert nicht.
Prüfen Sie die Datei nach jeder Änderung, bevor Sie sich auf sie verlassen:
reportedip-agent status endet mit Exit 2 und nennt den Schlüssel, wenn die Datei
nicht lesbar ist.
Jeder Schlüssel von config.yaml
Nichts hier ist Pflicht außer api_key. Jeder andere Schlüssel hat den gezeigten
Standard, und ein Schlüssel, den Sie weglassen, behält diesen Standard.
| Schlüssel | Standard | Wirkung |
|---|---|---|
api_key | keiner | Ihr API-Key. Der einzige Schlüssel ohne Standard. REPLACE_ME gilt als fehlend. |
api_url | https://reportedip.com/wp-json/reportedip/v2 | Die REST-Basis. Muss eine absolute https-URL sein; einfaches http ist nur auf dem Loopback erlaubt, für einen lokalen Proxy. |
update_url | aus api_url abgeleitet | Woher die Agent-Builds kommen. Ohne Angabe sind es Schema und Host von api_url mit dem Pfad /agent. Setzen Sie es für einen Spiegel, der dann ebenfalls https sein muss. |
auto_update | true | Im Sync-Lauf nach einem neueren Release suchen und es installieren. Auf false setzen, wenn die Version dieses Hosts anderswo entschieden wird, etwa durch Ihren eigenen Paketbau oder einen Canary-Rollout. reportedip-agent update funktioniert dann weiter von Hand, und status berichtet weiter, wie weit der Host zurück ist. |
log_level | info | info oder debug. Sonst nichts. |
log_file | /var/log/reportedip-agent.log | Das eigene Log des Agenten, zusätzlich zu stderr, damit journald alles behält, was es heute hat. Leer schaltet die Datei ab. Nur der Sync-Lauf und der Watch-Daemon schreiben dorthin. |
log_max_mb | 10 | Größe, bei der der Agent seine eigene Datei rotiert, geprüft bei jedem Schreiben. Bereich 1 bis 1024. |
log_keep | 3 | Behaltene rotierte Generationen, Bereich 0 bis 20. Mit den Standardwerten sind das im schlimmsten Fall 40 MB auf der Platte. Ein logrotate-Snippet ist nicht nötig, und es steht auch nicht im Weg. |
backend | auto | auto, ipset oder nftables. Siehe oben. |
mode | log | log, drop oder off. Gilt für die Regeln, also für die Feed-Listen und die lokalen Sperren. |
confidence | 90 | Der Feed-Schwellwert, 1 bis 100. Niedriger heißt längere Liste und mehr Grenzfälle. Der Server nennt eine Untergrenze für Ihren Tarif, 75 ab Professional und 90 auf Contributor, und von beiden Werten gilt der höhere. |
limit | 50000 | Höchstzahl Adressen pro Listenabruf, 1 bis 50000. |
lists | ssh, edge | Welche Feed-Listen aktiv sind. ssh und edge sind immer an und lassen sich nicht abschalten. lists.ssh.ports ist die einzige Option pro Liste; die anderen Listen haben feste Portsätze. |
ports | aus dem echten Listener | Unter lists.ssh: die Ports, auf die die ssh-Regel greift. Der Installer schreibt sie aus dem erkannten Listener. Eine leere Liste lässt die Regel auf jeden Port greifen. |
min_entries | ssh 1000, mail 500, web 500, ftp 500, edge 1000 | Die Plausibilitätsgrenze pro Liste: unter dieser Anzahl Adressen wird die Liste nicht getauscht. Mindestens 1, denn ein Minimum von null ließe eine leere Liste live gehen. |
whitelist_file | /etc/reportedip-agent/whitelist.conf | Ihre Nie-blocken-nie-melden-Liste. Eine Adresse oder ein CIDR pro Zeile, # beginnt einen Kommentar. Eine kaputte Zeile wird mit einer Warnung übersprungen und schaltet den Schutz nie ab. |
sources | ein sshd-Eintrag | Die Log-Quellen. Eine Datei mit einem sources-Schlüssel entscheidet allein, ein Eintrag von Ihnen muss also neben denen des Installers stehen und nicht an ihrer Stelle. |
type | keiner | Innerhalb einer Quelle: einer der dreizehn Quelltypen. Ein unbekannter Typ ist ein Fehler, der die gültigen aufzählt. |
path | keiner | Innerhalb einer Quelle: eine Logdatei. Setzen Sie path oder glob, nie beides. Ohne beides wählt der Agent den Kanal selbst, journald oder die Standarddatei der Distribution. |
glob | keiner | Innerhalb einer Quelle: ein Muster über viele Dateien, alle zehn Minuten neu aufgelöst. Höchstens fünf Wildcard-Segmente. |
exclude | keiner | Innerhalb einer Quelle: Muster, die Dateien wieder entfernen, die ein Glob erfasst hat. Shell-Muster, keine regulären Ausdrücke. Ein Muster ohne Schrägstrich passt auf den Dateinamen allein, eines mit Schrägstrich muss den vollen Pfad abdecken. Jedes Muster, das auf nichts passt, wird beim Start gemeldet. |
poll_minutes | 5 | Innerhalb einer Quelle: nur für imunify360, das ein Kommando abfragt statt eine Datei zu lesen. Bereich 1 bis 60. Bei jedem anderen Typ ist es ein Fehler. |
thresholds | leer | Überschreibt die eingebaute Tabelle pro Ereignisquelle. Siehe nächster Abschnitt. |
hits, window_minutes | siehe Tabelle unten | Innerhalb eines thresholds-Eintrags: das Paar, das „so viele Treffer in so vielen Minuten" bedeutet. |
min_hits, window_minutes | 5, 10 | Das globale Paar für jede Quelle ohne eigenen Eintrag in der eingebauten Tabelle. |
web_min_hits, web_window_minutes | 50, 120 | Dasselbe Paar für Web-Access-Logs, die Menge brauchen statt eines Statuscodes. |
dedup_hours | 6 | Dieselbe Adresse wird höchstens einmal pro diesem Fenster gemeldet. |
queue_max | 5000 | Wartende Report-Dateien. Darüber werden die ältesten verworfen. |
disk_min_mb | 200 | Freie Mebibyte, die dort vorhanden sein müssen, wo das Statusverzeichnis liegt. Darunter wird kein neuer Report eingereiht, während Erkennung und Blocken weiterlaufen. 0 schaltet die Grenze ab. |
jail_categories | eingebaute Tabelle | Zusätzliche Zuordnung von einem fail2ban-Jail-Namen zu Threat-Category-IDs, 1 bis 58. Nur relevant, solange fail2ban noch eine Quelle ist. |
ban | aus | Der Block für lokale Sperren, mit enabled, time_minutes, max_time_minutes, escalate und memory_hours. Siehe Blocken. |
notify | keine Mail | Der Mail-Block, mit email, cooldown_hours und dem Unterblock smtp (host, port, from, user, password, starttls). |
Eine vollständige Datei, mit jedem Block, den ein normaler Host benutzt:
# /etc/reportedip-agent/config.yaml root:root 0600
api_key: "YOUR_API_KEY"
api_url: https://reportedip.com/wp-json/reportedip/v2
log_level: info # info | debug
log_file: /var/log/reportedip-agent.log
log_max_mb: 10
log_keep: 3
auto_update: true
backend: auto # auto | ipset | nftables
mode: log # log | drop | off
confidence: 90 # the feed threshold
limit: 50000
lists: # ssh and edge are always on
ssh:
ports: [22] # written by install from the real listener
edge: {}
mail: {}
web: {}
min_entries: # below this many addresses a list is not applied
ssh: 1000
mail: 500
web: 500
ftp: 500
edge: 1000
whitelist_file: /etc/reportedip-agent/whitelist.conf
min_hits: 5 # the global detection pair
window_minutes: 10
web_min_hits: 50 # web access logs use their own
web_window_minutes: 120
dedup_hours: 6
queue_max: 5000
disk_min_mb: 200
sources: # detected at install time
- type: sshd
- type: web
glob: /var/www/*/log/access.log
- type: web-error
path: /var/log/nginx/error.log
- type: postfix
path: /var/log/mail.log
- type: dovecot
path: /var/log/mail.log
thresholds: {} # per source overrides, see below
ban: # block local finds, not only the feed
enabled: false
time_minutes: 30
max_time_minutes: 10080
escalate: 4
memory_hours: 24
notify:
email: "" # empty means no mail
cooldown_hours: 24
Erkennungsgrenzen, pro Quelle
Ein Schwellwert ist ein Paar: wie viele Treffer, innerhalb wie vieler Minuten. Das ist dieselbe Idee
wie maxretry und findtime eines fail2ban-Jails, und die Werte unten kommen
aus der Jail-Konfiguration des Hosts, auf dem das gemessen wurde. Fail2ban abzuschalten ändert also
nicht, wie empfindlich ein Dienst ist.
Drei Ebenen entscheiden, welches Paar für eine Ereignisquelle gilt, und die erste mit einer Antwort
gewinnt: ein ausdrücklicher Eintrag unter thresholds, dann die eingebaute Tabelle, dann
das globale Paar.
| Ereignisquelle | Schwellwert | Herkunft |
|---|---|---|
sshd | 5 in 10 Min. | min_hits / window_minutes |
web-error | 5 in 10 Min. | min_hits / window_minutes |
modsec | 5 in 10 Min. | min_hits / window_minutes |
exim | 5 in 10 Min. | min_hits / window_minutes |
web | 50 in 120 Min. | web_min_hits / web_window_minutes |
web-app | 20 in 60 Min. | eingebaut |
postfix-sasl | 3 in 60 Min. | eingebaut, gemessen |
postfix-reject | 5 in 60 Min. | eingebaut, nur 5xx-Rejects |
postfix-amavis | 3 in 60 Min. | eingebaut |
dovecot | 10 in 60 Min. | eingebaut, gemessen |
ftp | 20 in 60 Min. | eingebaut |
named | 20 in 30 Min. | eingebaut |
panel | 5 in 60 Min. | eingebaut |
fail2ban, csf, imunify360 | kein Schwellwert | Diese Quelle hat schon gezählt, eine Zeile ist also ein Report. |
Um eine Quelle und sonst nichts zu ändern, nennen Sie sie unter thresholds. Der
Schlüssel ist die Ereignisquelle aus der Tabelle oben, nicht der Quelltyp aus sources,
und ein Name, der nicht in dieser Liste steht, ist ein Fehler statt einer Einstellung, die nie
greift. Beide Zahlen müssen mindestens 1 sein.
# A recursive resolver that sees a lot of refused queries:
# fewer minutes, more hits, and nothing else changes.
thresholds:
named:
hits: 40
window_minutes: 5
# A mail server whose customers keep mistyping passwords:
# SASL a little more forgiving, Dovecot untouched.
thresholds:
postfix-sasl:
hits: 6
window_minutes: 60
Ein höherer Schwellwert macht den Agenten stiller und lässt langsame Angreifer durch. Ein niedrigerer ist die Richtung, die etwas kostet: unterhalb von etwa drei Treffern pro Stunde auf einer Mail- oder Web-Quelle melden Sie irgendwann einen Kunden mit einem falschen Passwort im Mailprogramm, und ein Report ist innerhalb der Community öffentlich. Das Web-Paar ist genau deshalb hoch, denn ein schlichtes WordPress antwortet auf ein falsches Passwort mit HTTP 200, und der Detektor kann sich nicht auf den Statuscode stützen.
Eine weitere Größe ist nicht konfigurierbar. Eine Adresse mit Bann-Historie braucht weniger Treffer als eine unbekannte, und das ist dieselbe Gewichtung, die das Recidive-Jail hatte: eine frühere Sperre zählt eine Zeile doppelt, zwei dreifach, dann fünffach und neunfach. Das Gewicht wird auf den Schwellwert der jeweiligen Ereignisquelle gekappt, eine zehnte Sperre macht also aus einer einzelnen Zeile keinen Report.
Bann-Grenzen
Vier Werte, alle im ban-Block, alle in der im Schlüssel genannten Einheit. Sie gelten
nur für Adressen, die der Agent in Ihren eigenen Logs gefunden hat. Die Community-Liste hat
überhaupt keine Sperrzeit, sie wird jede Stunde komplett ersetzt.
| Schlüssel | Standard | Bedeutung, und was an den Extremen passiert |
|---|---|---|
enabled | false | Ob lokale Funde überhaupt geblockt werden. false ist ein Host, der meldet und nicht blockt. Ein manuelles ban add funktioniert in beiden Fällen. |
time_minutes | 30 | Die erste Sperre einer Adresse. Mindestens 1. Sehr kurze Werte machen die Eskalation zum einzig Relevanten, sehr lange heißen, dass ein Fehlalarm lange im Set sitzt. |
max_time_minutes | 10080 (7 Tage) | Die Obergrenze der Eskalation. Darf nicht unter time_minutes liegen, sonst würde die Grenze die erste Sperre verkürzen, und der Agent lehnt so eine Datei ab. Ein späteres Senken verkürzt auch die schon laufenden Sperren: der nächste Sync stellt sie auf die heutige Obergrenze gekappt wieder her. |
escalate | 4 | Der Multiplikator pro Wiederholung innerhalb des Gedächtnisfensters. Mindestens 1, und 1 heißt, jede Sperre dauert time_minutes und es gibt gar keine Eskalation. |
memory_hours | 24 | Wie lange eine Sperre für die nächste Eskalation zählt. Mindestens 1. Ein Datensatz bleibt zusätzlich für die dreifache Länge seiner letzten Sperre erhalten, wenn das länger ist, und genau das macht die Obergrenze überhaupt erreichbar, ohne dass kurze Sperren die Bann-Datei wachsen lassen. |
# Careful: a short first ban, a low cap, a long memory.
ban:
enabled: true
time_minutes: 10
max_time_minutes: 1440 # one day
escalate: 3
memory_hours: 72
# Strict: a long first ban and a hard escalation.
ban:
enabled: true
time_minutes: 60
max_time_minutes: 43200 # thirty days
escalate: 6
memory_hours: 168 # a week
Betriebsgrenzen
Diese Werte begrenzen, was der Agent selbst verbraucht. Sie sind keine Stellschrauben für die Erkennung, und die zwei, die Sie wirklich einmal ändern wollen, sind die Queue-Größe und die Plattengrenze.
| Schlüssel | Standard | Einheit | Zu niedrig | Zu hoch |
|---|---|---|---|---|
queue_max | 5000 | wartende Report-Dateien | Reports gehen während eines API-Ausfalls verloren, die ältesten zuerst. | Ein langer Ausfall lässt Tausende kleiner Dateien übrig, die danach zu senden sind. |
dedup_hours | 6 | Stunden | Derselbe Angreifer wird immer wieder gemeldet und frisst Ihr Tageskontingent. | Eine Adresse, die nächste Woche wieder angreift, wird spät gemeldet. |
disk_min_mb | 200 | MB frei | Der Agent kann mithelfen, /var zu füllen, und das nimmt den ganzen Host mit. | Reports hören auf einem völlig gesunden Host auf. 0 entfernt die Grenze ganz. |
log_max_mb | 10 | MB | Rotation bei jedem zweiten Schreiben und eine Historie, die für keine Untersuchung reicht. | Zusammen mit log_keep ist das der schlimmste Fall auf der Platte. |
log_keep | 3 | Generationen | 0 behält gar keine rotierte Datei. | Maximal 20, und der Plattenbedarf ist das Produkt der beiden Werte. |
cooldown_hours | 24 | Stunden | Mindestens 1, und 1 heißt eine Mail pro Sync-Lauf für einen Zustand, der offen bleibt. | Ein Problem von heute Morgen wird morgen gemeldet. |
poll_minutes | 5 | Minuten | Ein Kommando, das auf einem belasteten Host zu oft startet. | Maximal 60, und Funde kommen entsprechend später an. |
limit | 50000 | Adressen pro Liste | Eine abgeschnittene Liste: die schlimmsten Adressen sind da, der Rest nicht. | 50000 ist das Maximum, das die API ausliefert. |
min_entries | 1000 / 500 | Adressen | Eine unplausibel kurze Liste geht live, und der Host ist schlechter geschützt, als er denkt. | Eine wirklich kleine Liste wird dauerhaft abgelehnt, und das Set bleibt auf seinem vorherigen Stand. |
Unterhalb der Plattengrenze reiht der Agent keine neuen Reports ein, notiert den Zustand und meldet
ihn per Mail, und erkennt und blockt weiter. Diese Reihenfolge hat einen Grund: ein voll gelaufenes
/var ist schlimmer als ein verlorener Report, und einen Server zu schützen, indem man
ihn kaputt macht, ist kein Schutz.
Mail, wenn etwas nicht stimmt
Ein leeres notify.email ist der Standard und heißt, dieser Host verschickt nichts.
Gemeldet wird ein Zustand und kein Ereignis, ein Feed, der jede Stunde scheitert, ist also eine
Nachricht und nicht vierundzwanzig. Der Agent führt acht Zustände (feed, api_key, chain, disk,
source, update, queue, license), merkt sich, wann jeder zuletzt gemeldet wurde, damit ein Neustart
nicht von vorn anfängt, und schickt eine Entwarnung, wenn einer vorbei ist.
# A host with a local MTA: postfix, exim or msmtp. The agent
# uses "sendmail -t -i" and no password lives in a file.
notify:
email: "ops@example.org"
cooldown_hours: 24
# A host without an MTA: SMTP, and starttls stays on.
notify:
email: "ops@example.org"
cooldown_hours: 12
smtp:
host: mail.example.org
port: 587
from: agent@example.org
user: agent@example.org
password: "..."
starttls: true
Mit starttls: true wird die Mail verweigert statt im Klartext geschickt, wenn der Server
kein STARTTLS anbietet. Eine Mail enthält den Namen des Zustands, die Version, einen allgemeinen Satz
mit Zahlen und den Befehl zum Nachsehen. Nie eine Logzeile, nie eine Adresse, nie einen Payload.
Führen Sie nach dieser Konfiguration reportedip-agent doctor aus: der Abschnitt
mail sagt, ob eine Mail den Host wirklich verlassen könnte, und das ist eine andere
Frage als die, ob die Konfiguration einliest.
Wann eine Änderung greift
Der Agent liest seine Konfiguration beim Start und beobachtet die Datei nicht, und es gibt kein Reload-Signal. Welcher Befehl nötig ist, hängt davon ab, welchen Teil Sie angefasst haben.
| Geändert | Was es greifen lässt |
|---|---|
mode, lists, min_entries, confidence, limit, backend | reportedip-agent sync. Der Sync-Lauf baut Kette und Regeln, ein neuer Modus ist also an seinem Ende aktiv. |
thresholds, min_hits, window_minutes, web_min_hits, web_window_minutes, dedup_hours, ban, notify, log_* | systemctl restart reportedip-agent.service. Das liest der Watch-Daemon. |
Eine Quelle in sources hinzugefügt | systemctl restart reportedip-agent.service. |
Eine Quelle aus sources entfernt | Ein Stop und ein Start, kein Restart. Auf einem Live-Host reichte ein systemctl restart nicht, und der Daemon las die entfernte Datei weiter: systemctl stop reportedip-agent.service && systemctl start reportedip-agent.service. |
Der Inhalt von whitelist_file | Nichts, wenn Sie reportedip-agent whitelist add benutzen: das schreibt Datei und Kernel-Set in einem Schritt und greift sofort. Ein Bearbeiten der Datei von Hand braucht einen sync. |
api_key, api_url, auto_update, update_url | Nichts für den nächsten sync, der ein Oneshot ist und die Datei frisch liest. Starten Sie den Watch-Dienst neu, damit auch der Meldepfad den Key übernimmt. |
# The safe sequence after any edit
reportedip-agent status >/dev/null && echo "config parses"
reportedip-agent sync
systemctl restart reportedip-agent.service
systemctl status reportedip-agent.service --no-pager
Der Community-Feed
Das ist der Teil, den die Seite Blockierung auf Netzwerkebene als Shell-Skript beschreibt. Der Agent macht dasselbe, und die Teile, die man beim Selberschreiben leicht falsch macht, sind schon erledigt: ein bedingter Abruf pro Liste, damit eine unveränderte Liste nichts kostet, eine Größenprüfung, bevor etwas live geht, ein atomarer Tausch, damit es nie ein Zeitfenster mit leerem Set gibt, und portgebundene Regeln, damit ein Web-Angreifer niemanden von SSH aussperrt.
Die Kategoriezuordnung ist dieselbe wie auf jener Seite. Welche der fünf Listen aktiv sind, hängt davon ab, was tatsächlich lauscht, und es gibt keine zusammengefasste Liste, denn ein Set pro Dienst ist das, was die portgebundene Regel erst möglich macht.
| Liste | Kernel-Set | Ports, auf die die Regel greift |
|---|---|---|
ssh | rip-ssh, rip-ssh-v6 | aus lists.ssh.ports |
mail | rip-mail, rip-mail-v6 | 25, 465, 587, 110, 995, 143, 993 |
web | rip-web, rip-web-v6 | 80, 443 |
ftp | rip-ftp, rip-ftp-v6 | 21 |
edge | rip-edge, rip-edge-v6 | jeden Port, mit Absicht |
Wie oft der Feed geholt wird, hängt von Ihrem Tarif ab, und das entscheidet der Server, nicht der Agent. Auf einem lizenzierten Server ist das Intervall ab Professional alle 15 Minuten bei einer Mindestvertrauenswürdigkeit von 75, auf Contributor stündlich bei 90. Business und Enterprise verhalten sich wie Professional. Der Agent fragt bei jedem Durchlauf, welche Werte für diesen Host gelten, und folgt der Antwort. Ein Upgrade wirkt also, ohne dass jemand eine Datei bearbeitet. Es gibt keinen Konfigurationsschlüssel für das Intervall, und ein Schlüssel, den Sie dafür erfinden, beendet den Agenten mit Exit 2.
Darüber liegen zwei weitere Regeln. Eine Liste, die vor weniger als 15 Minuten geholt wurde, wird
nicht erneut geholt, denn so lange hält der Server sie im Cache. sync von Hand zu
starten ist damit immer erlaubt und nie schädlich. Und jeder Abruf ist bedingt: eine unveränderte
Liste antwortet mit 304 und kostet eine Anfrage und keine Übertragung, und deshalb ist ein kurzes
Intervall für beide Seiten günstig.
Was der Agent in Ihren Logs findet
Jede Quelle hat ihren eigenen Detektor und ihren eigenen Schwellwert, denn fünf gescheiterte
SSH-Logins in zehn Minuten und fünfzig verdächtige Web-Anfragen in zwei Stunden sind dieselbe Aussage
über einen Angreifer und nicht dieselbe Zahl. Rotation, copytruncate und ein Log, das
eine Weile verschwindet, sind abgedeckt, und eine unlesbare Datei erzeugt eine Warnung statt einer
pro Lesevorgang.
Die dreizehn Quelltypen
| Typ | Typischer Pfad | Was als Treffer zählt |
|---|---|---|
sshd | journald, sonst /var/log/auth.log oder /var/log/secure | Falsche Passwörter, ungültige Benutzer, abgelehnte Keys für einen Benutzer, den es nicht gibt, überschrittene Versuchsgrenzen, und die Fehler vor der Authentifizierung, die Scanner ausmachen: kein Identification String, eine falsche Protokollversion, Müll im Banner-Austausch. Ein abgelehnter Key für einen gültigen Benutzer zählt bewusst nicht, denn ein Admin mit fünf Keys schreibt vier davon pro erfolgreichem Login. Ein erfolgreicher Login löscht die Fehlschläge dieser Adresse. |
web | /var/log/nginx/access.log oder ein Glob pro Site | Login-POSTs, unabhängig vom Statuscode gezählt, und Pfade, die kein legitimer Client abfragt. Alles andere in einem Access-Log wird ignoriert, denn das ist die Quelle mit echten Kunden dahinter. |
web-error | /var/log/nginx/error.log, /var/log/apache2/error.log | Anfragen, die der Webserver selbst abgelehnt hat, gescheiterte HTTP-Basic-Auth, und ModSecurity-Zeilen kritischer Schwere, wenn sie hier statt in einem Audit-Log landen. Zeilen von Rate Limits zählen bewusst nicht: ein Limit greift auch bei einem echten Browser mit zwanzig Tabs. TLS-Handshake- und PHP-Meldungen sagen etwas über den Server und nichts über den Client. |
web-app | dieselben Access-Logs | Läuft nach web auf denselben Zeilen und deckt die Angriffe auf Anwendungsebene ab: Benutzeraufzählung in WordPress, Abtasten von Plugins und Core, Login- und Exploit-Pfade von Drupal. Ein Login-POST wird einmal gezählt, von web. |
postfix | /var/log/mail.log, /var/log/maillog | Drei getrennte Ereignisquellen aus einer Datei: gescheiterte SASL-Authentifizierungen, NOQUEUE-Rejects, die wirklich 5xx sind (ein 450 ist Greylisting und zählt nicht), und Amavis-Blocks. Zugestellte Mail ist nie ein Treffer. |
dovecot | dasselbe Mail-Log | Gescheiterte IMAP- und POP3-Logins, einer pro Zeile, egal was „N attempts" sagt. Die entfernte Adresse kommt aus dem Feld rip=, nie aus lip=, denn das ist die eigene Adresse des Servers. Ein abgebrochener Login ohne Authentifizierungsversuch ist kein Treffer: das ist ein TLS-Scan, und es wurde kein Passwort probiert. |
exim | /var/log/exim4/mainlog, /var/log/exim/main.log | Gescheiterte Authentifizierungen und abgelehnte Absender. Nicht gegen einen Live-Host verifiziert: die Muster kommen aus dem dokumentierten Logformat. |
ftp | /var/log/syslog, /var/log/messages | Gescheiterte Authentifizierungen von pure-ftpd, proftpd und vsftpd. Alle drei loggen über syslog, und jeder schreibt die Gegenstelle anders, also werden drei Muster genutzt. pure-ftpd ist gemessen: 494 von 494 Zeilen auf einem Produktionshost hatten eine einzige Form. |
named | dasselbe syslog | Nur eine eingehende Anfrage, die bind abgewiesen hat. Die große Falle ist die umgekehrte Richtung: connection refused resolving ist der eigene Resolver dieses Hosts, der jemand anderes Nameserver nicht erreicht, und 90 Prozent der gemessenen Zeilen waren das. Ein Detektor ohne diese Ausnahme meldet fremde Nameserver als Angreifer. |
panel | /var/log/ispconfig/auth.log | Gescheiterte Logins am ISPConfig-Panel. Die Datei ist auf jedem gemessenen Host 0 Byte groß, und das ist kein Fehler: das Panel schreibt dort einfach nichts hin. doctor weist nach einer Woche darauf hin. |
modsec | /var/log/apache2/modsec_audit.log | Ein Ereignis pro Transaktion, deren Urteil kritische Schwere trägt. Das ist der einzige Detektor mit Zustand, denn eine Transaktion geht über mehrere Zeilen. Nichts aus der Anfrage reist im Ereignis mit: nicht die Regel-ID, nicht die passende Stelle, nicht die URI. |
csf | /var/log/lfd.log | Was CSF tatsächlich geblockt hat, nie was es nur erkannt hat. Kein zweiter Schwellwert darüber: lfd hat gezählt, bevor der Agent die Zeile sah, ein Block ist also ein Report. |
fail2ban | /var/log/fail2ban.log, sonst das Journal der Unit | Nur Bann-Aktionen. Ein Restore Ban wird nie gemeldet, denn das spielt ein fail2ban-Neustart aus seiner eigenen Datenbank nach und ist kein neuer Angriff. Eine Found-Zeile eines Filters wird auch nicht gemeldet: das Jail hat noch nicht entschieden. |
imunify360 | fragt imunify360-agent ab | Vorfälle aus dem CLI, über das Präfix des Regelnamens Kategorien zugeordnet. Experimentell und nicht gegen eine lizenzierte Installation verifiziert; der Decoder überspringt, was er nicht lesen kann, statt aus einer unerwarteten Antwort eine tote Quelle zu machen. |
Eine Quelle nachtragen, die der Installer nicht fand
Eine Quelle, die der Installer nicht gefunden hat, fehlt einfach in der Config, und sie nachzutragen
ist ein Eintrag mit einem Pfad oder einem Glob. Weil eine Datei mit einem sources-Block
die Standardliste vollständig ersetzt, gehört Ihr Eintrag neben die bestehenden und nicht in einen
zweiten Block.
sources:
- type: sshd
- type: web
path: /var/log/nginx/access.log
# A second web server on a different path
- type: web
path: /var/log/caddy/access.log
# Every site of a panel host, rescanned every ten minutes.
# At most five wildcard segments.
- type: web
glob: /var/www/clients/*/web*/log/access.log
exclude:
# This site reports to the API on its own, through Hive or a
# honeypot. Without the exclude the host sends every address
# twice and pays twice out of the daily quota.
- /var/log/ispconfig/httpd/honeypot.example.com/*
# Exim on a host the installer saw as a Postfix machine
- type: exim
path: /var/log/exim4/mainlog
Zwei Pfade, die auf dieselbe Datei zeigen, sind kein Problem und brauchen kein exclude: ISPConfig
veröffentlicht jedes Access-Log zweimal, unter /var/www und unter
/var/log/ispconfig, und der Agent liest so eine Datei einmal. Bevor Sie einem neuen
Eintrag vertrauen, halten Sie reportedip-agent test an die Datei, starten dann den
Watch-Dienst neu und schauen in status: der Abschnitt sources zeigt Treffer
pro Quelle, und eine Quelle mit files= null löst auf gar nichts auf.
Was die Maschine verlässt
Ein Report enthält die Adresse, die IDs der Threat Categories und einen generierten Satz. Das ist alles. Keine Logzeile, kein Benutzername, kein Request-Body, kein User-Agent und keine URL wird je übertragen, ein Report kann also auch aus Versehen nicht Ihre Kunden, Ihre Pfade oder Ihre Zugangsdaten verraten.
In der aktuellen Version sendet der Agent keinen Hostnamen. Ein Server weist sich der API gegenüber mit einer zufälligen UUID aus, die bei der Installation erzeugt wurde, und das ist die Identität, die Sie in Ihrem Konto sehen. Ein Label vergeben Sie dort, wenn Sie den Server wiedererkennen wollen; das Label bleibt im Konto und wird nie aus der Maschine abgeleitet.
Vier Dinge werden nie gemeldet und nie geblockt, und das ist eine Grenze im Code statt einer Einstellung: private und reservierte Bereiche, das Loopback, jede Adresse der eigenen Interfaces dieses Servers samt Default-Gateway, und alles in Ihrer Whitelist. Die SSH-Client-Adresse aus der Installation steht in der Auto-Whitelist und gehört damit zur letzten Gruppe.
Blocken
Der Agent schreibt zwei sehr verschiedene Dinge in den Kernel, und wer von fail2ban kommt, verwechselt sie in der ersten Woche meistens. Sie haben verschiedene Quellen, verschiedene Lebensdauern und verschiedene Schalter, es lohnt sich also, das einmal richtig zu trennen.
Zwei Arten von Set, zwei Lebensdauern
| Community Blacklist | Lokale Funde | |
|---|---|---|
| Sets | rip-ssh, rip-mail, rip-web, rip-ftp, rip-edge, und je ein -v6-Set dazu | rip-local und rip-local-v6 |
| Woher die Adressen kommen | Von jedem Melder der Community, gefiltert über Ihr confidence | Nur aus den eigenen Logs dieses Hosts |
| Wie ein Eintrag hineinkommt | Das ganze Set wird bei jedem Feed-Durchlauf ersetzt | Eine Adresse auf einmal, wenn ein Schwellwert erreicht ist |
| Wie ein Eintrag verschwindet | Mit dem nächsten Tausch, wenn der Feed sie nicht mehr führt | Der Kernel lässt ihn ablaufen, wenn sein eigenes Timeout um ist |
| Timeout pro Eintrag | keines | ja, das ist der ganze Entwurf |
| Schalter | mode | ban.enabled, und mode darüber |
| Braucht eine Lizenz | ja, das ist der bezahlte Teil | nein |
Der Feed-Tausch fasst rip-local nie an. Feed-Sets werden vollständig ersetzt und
haben kein Timeout; lokale Sperren kommen einzeln und laufen von selbst ab. Diese Trennung ist der
Grund, warum ein Feed-Ausfall Ihre lokalen Sperren nicht lösen kann, und warum eine lokale Sperre
nicht als Waise überlebt, nachdem das Feed-Set neu gebaut wurde.
Wie eine lokale Sperre entsteht und wie sie endet
Eine Sperre entsteht, wenn der Zähler eines Detektors für eine Adresse den Schwellwert ihrer Ereignisquelle überschreitet. Was dann passiert, in dieser Reihenfolge:
- Die Whitelist wird zuerst geprüft, bevor überhaupt etwas anderes gefragt wird. Eine Adresse auf
der Whitelist hinterlässt gar keine Spur, Sie finden also Ihren eigenen Management-Bereich nie in
reportedip-agent ban listund fragen sich, ob er geblockt war. Die Prüfung sagt, welche Schicht gegriffen hat: ein eingebauter reservierter Bereich, eine der eigenen Adressen dieses Hosts, oder Ihre Datei. - Der Bann-Speicher,
/var/lib/reportedip-agent/bans.json, wird nach der Sperrzeit gefragt. Er hält die Adresse, wann die Sperre abläuft, wie viele Sperren ins Gedächtnisfenster fielen, wann die letzte begann, die Quelle und die Kategorien. Die Datei wird vor dem Kernel-Eintrag geschrieben, ein Absturz direkt nach dem Kernel-Schreiben kann also nicht den Datensatz verlieren, der die Sperre wieder aufhebt. - Die Adresse kommt mit dieser Zeit als Timeout pro Eintrag in
rip-local. Der Kernel lässt sie ablaufen. Es gibt keinen Aufräum-Timer, keinen Cronjob und keine Entsperr-Warteschlange, und genau deshalb hinterlässt ein abgestürzter oder entfernter Agent keine dauerhafte Sperre. - Eine Zeile geht ins Log, mit der Adresse, der Sperrzeit, der Quelle, der Zahl der Sperren dieser Adresse im Fenster, dem Abstand zwischen Logzeile und Kernel-Eintrag und den zwei Befehlen, mit denen man das rückgängig macht.
Eine laufende Sperre wird nie verkürzt. Kommt ein neuer Treffer für eine Adresse, die schon gesperrt
ist, passiert nichts: es ist auch keine Eskalation, denn die Eskalation zählt Sperren und nicht
Treffer, genau wie das Recidive-Jail, das sie ersetzt. Eine Adresse, die schon geblockt ist, kann
nicht noch einmal geblockt werden. Diese Regel hält auch die Übergangszeit sauber, in der der Agent
einen Angriff zweimal sieht, einmal als rohe Zeile aus auth.log und einmal als
Bann-Zeile aus fail2ban.log.
Eine nachgespielte Logzeile erzeugt ebenfalls keine Sperre. Ein Treffer, dessen Zeitstempel nicht neuer ist als die letzte Sperre dieser Adresse, ist ein Replay nach einem harten Stop und kein neues Vergehen, und der Meldepfad hat denselben Schutz in seiner Dedup-Datei.
Der Zustand überlebt mehr als einen Neustart. Jeder Sync-Lauf vergleicht bans.json mit
dem, was der Kernel wirklich hält, und stellt das Fehlende mit der Restzeit wieder her:
- Nach einem Reboot sind das alle, denn weder ein ipset-Timeout noch das Set selbst
überlebt einen Reboot. Deshalb ist der Sync-Dienst für
multi-user.targetaktiviert und läuft nach jedem Firewall-Dienst. - Im normalen Betrieb ist es, was das Set weggenommen hat: ein
firewall-cmd --reload, eincsf -r, einipset flush. Einträge, die der Kernel noch hat, bleiben unangetastet, die Lücke ist also ein Teil eines Sync-Intervalls und nicht der Rest der Sperre. Das Log sagt ausdrücklich, wenn Einträge unter laufenden Sperren fehlten, denn das heißt, dass etwas das Set unter dem Agenten bearbeitet hat. - Ein abgelaufener Datensatz kommt nie zurück. Der Angreifer von gestern ist kein Grund, heute jemanden abzuschneiden.
- Die Whitelist wird bei jeder Wiederherstellung neu geprüft. Sie kann gewachsen sein, während der Host unten war, und eine Adresse, die Sie gestern auf die Whitelist gesetzt haben, darf nicht durch einen Datensatz vom Vortag wieder geblockt werden.
Eskalation, mit echten Zahlen
Die erste Sperre dauert time_minutes. Jede Wiederholung innerhalb des
Gedächtnisfensters multipliziert sie mit escalate, und max_time_minutes
deckelt sie. Mit den Standardwerten (30 Minuten, Multiplikator 4, Obergrenze eine Woche) geht eine
Adresse, die immer wiederkommt, so:
| Sperre | Rechnung | Dauer |
|---|---|---|
| 1. | time_minutes | 30 Minuten |
| 2. | 30 × 4 | 2 Stunden |
| 3. | 120 × 4 | 8 Stunden |
| 4. | 480 × 4 | 32 Stunden |
| 5. | 1920 × 4 | 128 Stunden, fünf Tage und acht Stunden |
| 6. und weiter | wären 512 Stunden, gedeckelt | 7 Tage, der Wert von max_time_minutes |
Konkret durchgerechnet. Ein Angreifer klopft am Montag um 09:00 an Ihren SSH-Port und erreicht fünf Fehlschläge innerhalb von zehn Minuten, um 09:07 gibt es also eine Sperre von 30 Minuten, die um 09:37 abläuft. Um 11:00 kommt er wieder und wird erneut gesperrt, diesmal für zwei Stunden, denn die erste Sperre liegt noch im Gedächtnis von 24 Stunden. Der dritte Versuch um 14:00 kostet acht Stunden und bringt ihn bis 22:00. Der vierte, früh am Dienstag, kostet 32 Stunden. Ab da bleibt der Datensatz für die dreifache Länge der letzten Sperre erhalten statt für die glatten 24 Stunden, und genau das macht die fünfte Stufe überhaupt erreichbar: eine lange Sperre ist ein langes Gedächtnis wert, eine Sperre von 30 Minuten nur den konfigurierten Tag, und die Bann-Datei wächst deshalb nicht durch kurze Sperren.
Zwei Einstellungen ändern die Form dieser Kurve. escalate: 1 schaltet die Eskalation
ganz ab und gibt jeder Sperre dieselbe Länge. Ein memory_hours, das relativ zu
time_minutes kurz ist, heißt, dass eine Adresse nach einem Tag Pause wieder Ersttäter
ist, und das ist für einen Mailserver mit echten Kunden manchmal genau richtig.
Ein Senken von max_time_minutes gilt auch für Sperren, die schon laufen. Der nächste
Sync stellt sie auf die heutige Obergrenze gekappt wieder her, denn wer die Obergrenze nach einem
Vorfall senkt, erwartet, dass die laufenden Sperren folgen, statt eine Woche im Kernel zu sitzen.
Die Kette im Kernel
Mit dem ipset-Backend besitzt der Agent genau eine Kette, rip-blacklist, und einen
Sprung dorthin. Die Kette wird bei jedem Sync geleert und neu gebaut, ihr Inhalt ist also immer das,
was die Config sagt, und der Sprung wird nur an Position 1 von INPUT eingefügt, wenn er
nicht schon da ist.
# What a sync builds, in this order:
iptables -N rip-blacklist
iptables -F rip-blacklist
iptables -A rip-blacklist -m set --match-set rip-whitelist src -j RETURN
iptables -A rip-blacklist -m set --match-set rip-local src -j DROP
iptables -A rip-blacklist -p tcp --dport 22 \
-m set --match-set rip-ssh src -j DROP
iptables -A rip-blacklist -p tcp -m multiport --dports 25,465,587,110,995,143,993 \
-m set --match-set rip-mail src -j DROP
iptables -A rip-blacklist -p tcp -m multiport --dports 80,443 \
-m set --match-set rip-web src -j DROP
iptables -A rip-blacklist -m set --match-set rip-edge src -j DROP
iptables -I INPUT 1 -j rip-blacklist
Die Whitelist ist die erste Regel und springt zurück, sie ist nicht die letzte Regel.
Ein RETURN vor allem anderen heißt, dass eine Adresse auf der Whitelist die Kette
verlässt, bevor irgendein Set befragt wird, sie steht also über jeder Sperre, auch über einer, die
schon in rip-local liegt. Das macht whitelist add zu einem funktionierenden
Weg aus einer Aussperrung, ohne Sync und ohne Neustart. Eine Whitelist am Ende wäre eine Liste von
Ausnahmen, die zu spät kommen, und auf einem Host, auf dem Sie sich ausgesperrt haben, ist „zu spät"
das ganze Problem.
Die Regel für lokale Sperren hat keine Portbindung, denn ein Host, der Ihren
Mailserver angegriffen hat, hat auf Port 22 auch nichts zu suchen. Die fünf Feed-Regeln sind
portgebunden, eine Adresse auf der Web-Liste wird also auf 80 und 443 verworfen und erreicht SSH
weiterhin. Das ist Absicht: eine geteilte Adresse, ein Carrier-NAT oder ein übernommener Proxy auf der
Web-Liste darf keinen Administrator von der Maschine aussperren. Nur edge greift auf
jeden Port, und das ist es, was die Kategorie dahinter bedeutet.
Mit dem nftables-Backend ist die Form dieselbe, nur nativ: eine Tabelle inet reportedip,
eine Kette, die mit Priorität -10 und Policy accept in input hängt, zuerst die zwei
return-Regeln der Whitelist, dann rip-local, dann die Feed-Listen mit ihren
Portbindungen. Die Whitelist-Sets sind Intervall-Sets, damit sie CIDR-Bereiche halten können; die
lokalen Sets tragen das Timeout-Flag, das beide Werkzeuge am Set verlangen, bevor ein Element
überhaupt ein Timeout tragen darf.
In mode: log werden dieselben Regeln gebaut, und das Urteil ist eine ratenbegrenzte
Logzeile (sechs pro Minute, mit dem Präfix rip-<liste>:) statt
DROP. Alles andere ist gleich, und deshalb ist der Log-Modus eine echte Probe und keine
Simulation.
mode und ban.enabled sind zwei Schalter
Das ist das häufigste Missverständnis, es bekommt also seinen eigenen Absatz. mode
entscheidet, was die Regeln tun. ban.enabled entscheidet, ob Ihre eigenen Funde
überhaupt je ein Eintrag werden. Wer nur mode: drop setzt, hat die Community-Liste
durchgesetzt und von seinen eigenen Funden nichts.
mode | ban.enabled | Community-Liste | Ihre eigenen Funde |
|---|---|---|---|
log | false | Greift und loggt, nichts wird verworfen | Werden an die Community gemeldet, lokal nicht geblockt |
log | true | Greift und loggt | Werden in rip-local erfasst und sind in ban list sichtbar, geloggt statt verworfen |
drop | false | Wird verworfen | Nur gemeldet. Das ist ein völlig sinnvoller Dauerzustand. |
drop | true | Wird verworfen | Wird ebenfalls verworfen, mit Eskalation. Die vollständige Konfiguration. |
off | beides | Nichts im Paketpfad: der Sprung wird entfernt, die Kette bleibt mit ihren Regeln | Im Speicher erfasst, ohne Wirkung |
off ist der Notschalter und ist darin ehrlich. Es entfernt, was die Kette in den
Paketpfad hängt, bis zu fünfmal, um doppelte Sprünge zu erwischen, und bricht laut ab, wenn ein
Sprung überlebt, denn „off" zu sagen und weiter zu verwerfen ist schlimmer als ein Fehler. Die Sets
behalten ihre Einträge, ein Zurückschalten braucht also keinen vollen Download.
Eine Sperre von Hand ignoriert beide Schalter mit Absicht: reportedip-agent ban add
funktioniert auch bei ban.enabled: false, denn das ist eine bewusste Handlung eines
Operators, so wie fail2ban-client set banip es war. Die Whitelist gilt weiterhin, und
auf einem Host ohne Firewall-Backend verweigert der Befehl den Dienst.
Von log auf drop wechseln
# 1. What would have been dropped? The rules already match in
# log mode, so ask the kernel log.
journalctl -k --since "24 hours ago" | grep -c "rip-"
journalctl -k --since "24 hours ago" | grep -o "rip-[a-z]*:" | sort | uniq -c
# 2. Is anything of yours in there? Check every source address
# against your whitelist before you switch.
reportedip-agent whitelist list
# 3. Switch, and rebuild the rules.
sed -i "s/^mode: log/mode: drop/" /etc/reportedip-agent/config.yaml
reportedip-agent sync
reportedip-agent status
# 4. Only now the second switch, if you want it.
# ban.enabled: true, then restart the daemon.
systemctl restart reportedip-agent.service
reportedip-agent ban list
Wenn Schritt 1 eine Zahl im Tausenderbereich liefert, ist das auf einem exponierten Host normal und es ist die Community-Liste bei der Arbeit. Entscheidend ist nicht die Anzahl, sondern ob irgendeine Adresse in diesem Log zu Ihnen gehört. Zwei Tage im Log-Modus reichen, um das herauszufinden, und die Antwort ist hier deutlich günstiger als nach dem Wechsel.
Nachsehen, was wirklich im Kernel steht
reportedip-agent status ist die Zusammenfassung, und es liest sowohl die Statusdateien
als auch den laufenden Kernel, damit man beides vergleichen kann. Wo die zwei sich widersprechen, ist
der Kernel die Wahrheit, und status sagt das: ein Datensatz ohne Kernel-Eintrag ist eine Sperre, die
nicht wirkt.
# The agent's own view
reportedip-agent status
reportedip-agent ban list
# ipset backend, straight from the kernel
ipset list -t rip-ssh # header and entry count only
ipset list rip-local # entries, each with its timeout
iptables -S rip-blacklist
iptables -L INPUT -n --line-numbers | head
# nftables backend
nft list table inet reportedip
nft list set inet reportedip rip-local
In ban list ist die Spalte kernel das, was der Kernel noch auf der Uhr hat,
und record das, was bans.json erwartet. Ein Strich unter
kernel neben einem laufenden Datensatz heißt, die Sperre wirkt nicht und der nächste
Sync stellt sie wieder her. Eine Zeile, deren Datensatz none sagt, existiert nur im
Kernel, also hat jemand ipset oder nft von Hand benutzt, oder der Speicher
ist verloren gegangen: sie läuft trotzdem ab, aber kein Reboot bringt sie zurück.
Eine Sperre aufheben, und alles zurückbauen
reportedip-agent whitelist add <adresse> wirkt also sofort und
steht über jeder Sperre, auch über einer, die schon im Set liegt. Der Befehl schreibt die Datei
und das laufende Kernel-Set in einem Schritt und braucht weder Sync noch Neustart.
# Lift one ban and forget its history. The next detection starts
# from a first offence rather than escalating on top of a verdict
# you disagreed with.
reportedip-agent unban 203.0.113.45
# Never ban and never report this address or range, from now on.
reportedip-agent whitelist add 203.0.113.0/24 "customer office"
# Ban by hand. Works even with ban.enabled: false. A time given
# here is the time, not the first step of an escalation.
reportedip-agent ban add 203.0.113.45
reportedip-agent ban add 203.0.113.45 1440
# Stop blocking without uninstalling: no jump, chain and sets kept.
sed -i "s/^mode: .*/mode: off/" /etc/reportedip-agent/config.yaml
reportedip-agent sync
# Remove the agent from the packet path completely (ipset backend).
iptables -D INPUT -j rip-blacklist; iptables -F rip-blacklist; iptables -X rip-blacklist
ip6tables -D INPUT -j rip-blacklist; ip6tables -F rip-blacklist; ip6tables -X rip-blacklist
for s in $(ipset list -n | grep "^rip-"); do ipset destroy "$s"; done
# nftables backend
nft delete table inet reportedip
unban und whitelist add nehmen beide das Sync-Lock, der
Wiederherstellungsschritt eines laufenden Syncs kann also nicht zurücklegen, was Sie gerade aufheben.
Einen Eintrag aus der Whitelist-Datei zu entfernen ist der eine Vorgang, der nicht sofort wirkt: er
greift mit dem nächsten Sync-Neubau, und eine Ausnahme zu entfernen muss nie sofort passieren.
rip--Set verweisen.
iptables-restore verwirft die ganze Datei, sobald es auf ein unbekanntes Set trifft,
eine übrig gebliebene Zeile in /etc/iptables/rules.v4 kann Ihnen also beim nächsten
Boot die komplette Firewall nehmen. Der Agent baut seine Kette bei jedem Boot selbst auf und
braucht nichts Gespeichertes. status warnt, wenn es rip- in
rules.v4, rules.v6, /etc/sysconfig/iptables,
ip6tables, /etc/nftables.conf oder /etc/nftables.d
findet.
Befehle
| Befehl | Wirkung | Exit |
|---|---|---|
install [--key K] [--admin-ip IP] [--ssh-port N] | Erkennt die Dienste, schreibt Config, Auto-Whitelist und Install-ID, installiert und aktiviert die Units und prüft den Key. Überschreibt eine bestehende Config nie. Nur als root. | 0, 1 bei abgelehntem Key, 2 bei einem Config-Problem |
sync | Ein Feed-Durchlauf: Whitelist-Set neu bauen, jede Liste bedingt abrufen, tauschen, was die Größenprüfung bestanden hat, Kette neu bauen, fehlende lokale Sperren wiederherstellen, aufräumen, alle sechs Stunden nach einem Update sehen. Das führt der Timer aus, und das läuft beim Boot. | 0, 1 eingeschränkt, ebenfalls 0, wenn ein anderer Sync das Lock hält |
watch | Der Daemon. Liest jede Quelle mit, zählt, meldet und sperrt, wenn das eingeschaltet ist. Endet bei SIGTERM. | 1, wenn das Queue-Lock nach einer Minute noch gehalten wird, 2 bei einem Config-Problem |
report-queue | Schickt die wartenden Reports einmal. Nützlich nach einem API-Ausfall oder auf einem Host, auf dem der Daemon nicht läuft. | 0, 1 eingeschränkt |
status | Version, Backend, Modus, Werkzeuge, Anzahl und letzter Erfolg pro Liste, Whitelist, Kettenprüfung, Lesepositionen und Treffer pro Quelle, Queue und Sender, Konto und Lizenz, Platte, lokale Sperren, offene Zustände. | 0 gesund, 1 eingeschränkt, 2 Config |
doctor | Was der Host bietet und was fehlt. Ändert nichts, funktioniert ohne Config. | 0, 1 mit Einschränkungen, 2 nicht lauffähig |
test <datei>... [--type T] [--lines] | Lässt die Detektoren über echte Logdateien laufen. Meldet nichts, sperrt nichts, schreibt nichts. | 0, 2 bei einem Datei- oder Typproblem |
ban list | add <ip> [minuten] | rm <ip> | Zeigt die lokalen Sperren gegen das, was der Kernel wirklich hält, setzt eine von Hand, hebt eine auf. | 0, 1 bei einem Kernel-Fehler, 2 bei falschem Argument |
unban <ip> | Dasselbe wie ban rm, unter dem Wort, das ein Operator tippt, wenn es brennt. | wie oben |
whitelist add <ip|cidr> [kommentar] | list | rm <ip|cidr> [--auto] | Pflegt die Nie-blocken-nie-melden-Liste. add schreibt Datei und Kernel-Set auf einmal. list gibt Ihre Datei und die Auto-Whitelist aus. --auto entfernt einen Eintrag, den der Installer geschrieben hat. | 0, 1 wenn die Datei geändert wurde und das Set nicht, 2 bei einer falschen Adresse |
update [--check] | Prüft den Verteilpunkt, ersetzt diese Binärdatei und startet danach den Watch-Dienst neu. --check berichtet nur. Das ist der eine Befehl, der die Config locker liest, er funktioniert also auch auf einem Host, dessen Config neuer ist als seine Binärdatei. | 0, 1 wenn die Prüfung oder die Installation scheiterte |
housekeeping | Entfernt die eigenen Überreste des Agenten und gibt die Zahlen aus. Der Sync-Lauf macht dasselbe still. | 0, 2 bei einem Config- oder Zustandsproblem |
version | Gibt die Version aus und sonst nichts. | 0 |
help | Die Befehlsliste, mit den Pfaden für Config und Zustand. | 0 |
test, statt fail2ban-regex
test lässt die Detektorkette über eine Logdatei laufen, die Sie schon haben, mit den
Schwellwerten und der Whitelist dieses Hosts, und gibt aus, welche Adressen einen Schwellwert
überschritten hätten und an welcher Stelle der Datei. Es meldet nichts, blockt nichts und schreibt
nichts, es ist also auf einem Produktionshost gefahrlos und die ehrliche Antwort auf die Frage, ob
das den Angriff von letzter Woche erwischt hätte.
# A configured source: the type is taken from the config
reportedip-agent test /var/log/auth.log
# Any other file: name the type yourself
reportedip-agent test --type postfix /var/log/mail.log.1
# A rotated log and its successor as one stream, in this order,
# so a window that spans the rotation counts like the daemon saw it.
# A .gz is read inflated.
reportedip-agent test /var/log/mail.log.2.gz /var/log/mail.log.1 /var/log/mail.log
# Every single hit, with line number, address and timestamp
reportedip-agent test --lines /var/log/auth.log
Die Zusammenfassungszeile nennt die gelesenen Zeilen, wie viele passten, wie viele keinen brauchbaren Zeitstempel trugen und wie viele als überlang übersprungen wurden. Danach eine Zeile pro Adresse mit ihren Treffern, ihren Zurücksetzungen, ob sie gesperrt worden wäre und wie oft, dem Zeitpunkt des ersten Treffers und dem angewendeten Schwellwert. Eine Adresse auf Ihrer Whitelist wird mit der Schicht gezeigt, die gegriffen hat, und als nie gesperrt und nie gemeldet markiert. Das macht diesen Befehl zum schnellsten Weg, einen Whitelist-Eintrag tatsächlich nachzuweisen.
Zwei Dinge macht test nicht. Es rät kein Format: ohne --type muss die Datei
einer der konfigurierten Quellpfade sein, sonst sagt es das und zählt die gültigen Typen auf. Und es
wendet die Gewichtung aus der Bann-Historie nicht an, der Daemon braucht für eine Adresse mit
früheren Sperren also weniger Treffer, als diese Wiederholung vermuten lässt.
Betrieb
- Ein Timer im Takt Ihres Tarifs, mit Streuung.
reportedip-agent-sync.timerfeuert wenige Minuten nach seiner Aktivierung und danach wiederholt in dem Intervall, das Ihr Tarif mitbringt, mit zufälligem, aber festem Versatz, damit eine Flotte die API nicht in derselben Sekunde erreicht. Welches Intervall das ist, sagt der Server, siehe Der Community-Feed. Der Boot-Pfad ist getrennt:reportedip-agent-sync.serviceist fürmulti-user.targetaktiviert und läuft nachnetwork-online.targetund nach jedem Firewall-Dienst, ohne Zufallsversatz, denn ein Host darf nach einem Reboot keine Viertelstunde ungeschützt sitzen. - Ein Watch-Dienst, der stehen bleibt, wenn er soll.
reportedip-agent.servicestartet nach einem Fehler nach zehn Sekunden neu, höchstens fünfmal in fünf Minuten, und nie bei Exit-Code 2. Ein falsch konfigurierter Host bleibt mit einem lesbaren Grund stehen, statt endlos neu gestartet zu werden. Beide Units laufen mitNoNewPrivileges,ProtectHome,PrivateTmp, gesperrter Personality und einem eingeschränkten Satz an Adressfamilien. - Eigenes Log, eigene Rotation. Der Agent schreibt nach stderr, was journald
aufnimmt, und in seine eigene Datei, wenn
log_filegesetzt ist. Diese Datei rotiert er selbst beilog_max_mbund behältlog_keepGenerationen. Er hängt nicht an logrotate und füllt das Journal nicht. - Eine Mail, wenn etwas nicht stimmt, eine, wenn es behoben ist. Pro Zustand, nicht pro Ereignis, mit einer Wartezeit, ein kaputter Feed erzeugt also eine Nachricht und nicht eine pro Stunde.
- Eine Plattengrenze. Unterhalb von
disk_min_mbreiht der Agent keine neuen Reports ein und sagt das, während Erkennung und Blocken weiterlaufen. housekeeping. Alte Queue-Dateien, abgelaufene Dedup-Einträge, alte Lesepositionen für Dateien, die es nicht mehr gibt, übrige temporäre und Lock-Dateien, abgelaufene Bann-Datensätze, die keine Eskalation mehr speisen, und die vorherige Binärdatei, sobald sie einen Monat alt ist. Läuft bei jedem Sync mit, und von Hand, wenn Sie die Zahlen sehen wollen.- Selbst-Update alle sechs Stunden. Ein neues Release wird vor der Installation gegen eine Ed25519-Signatur mit dem in die Binärdatei kompilierten öffentlichen Schlüssel geprüft, ein manipulierter Download scheitert also auf Ihrer Maschine, statt als vertrauenswürdig zu gelten, weil er über HTTPS kam. Die vorherige Binärdatei bleibt für ein Rollback liegen und wird nach dreißig Tagen vom Housekeeping entfernt.
systemctl list-timers reportedip-agent-sync.timer
systemctl status reportedip-agent.service --no-pager
journalctl -u reportedip-agent.service -n 50 --no-pager
journalctl -u reportedip-agent-sync.service -n 50 --no-pager
tail -n 100 /var/log/reportedip-agent.log
Exit-Codes
| Code | Bedeutung | Was zu tun ist |
|---|---|---|
0 | Gesund | Nichts. |
1 | Eingeschränkt, aber es wird wieder versucht | Die Ausgabe lesen. Ein weiterer Versuch kann das durchaus beheben. Ein offener Fehlerzustand im Gesundheitsstand färbt den Exit-Code auch dann, wenn der Lauf selbst durchging, denn ein Exit 0 neben einem erfassten Fehler ist kein Signal für ein Monitoring. |
2 | Ohne Menschen nicht wiederholbar | Die Config, die Dateirechte, ein fehlendes Werkzeug, ein Lock in einem anderen Prozess. doctor ausführen. systemd startet den Watch-Dienst bei einer 2 nicht neu. |
Damit ist reportedip-agent status direkt als Monitoring-Prüfung verwendbar, ohne
Wrapper-Skript und ohne Ausgabe zu parsen.
Upgrades und Release Notes
Der Agent sucht alle sechs Stunden nach einem neuen Release, innerhalb des Sync-Laufs. Er prüft den
Download gegen eine Ed25519-Signatur mit dem in die Binärdatei eingebauten öffentlichen Schlüssel,
behält die vorherige für ein Rollback und startet den Watch-Dienst selbst neu.
reportedip-agent update macht dasselbe auf Wunsch, und update --check
berichtet nur, was veröffentlicht ist.
Den Install-Befehl erneut auszuführen aktualisiert einen Host ebenfalls, und das ist der Weg, wenn ein Release die Mindestversion anhebt: der Agent verweigert dann das Selbst-Update und sagt das, denn er braucht einen Menschen. Downgrades werden generell abgelehnt, ein Host, der eine neuere Version geholt hat, geht also nicht von allein zurück.
Ein Upgrade-Fall lohnt sich im Vorfeld zu kennen. Der Config-Parser ist streng bei unbekannten
Schlüsseln, eine älteres Binary kann also eine Config nicht lesen, die schon einen neueren Block
trägt. Für einen Kunden ist die Reihenfolge harmlos, denn der Agent aktualisiert sich zuerst, und ein
neuer Schlüssel erscheint erst, wenn ihn jemand hinzufügt. Sollten Sie doch einmal eine Binärdatei
haben, die älter ist als ihre Config, ist update der Ausweg: es ist der eine Befehl, der
die Datei locker liest, und es nennt die Schlüssel, die es nicht kennt.
Was das aktuelle Release geändert hat, ist öffentlich und braucht keinen Key:
curl -s https://reportedip.com/agent/whats-new
reportedip-agent update --check
Änderungen an der REST-API selbst, also Response-Felder und Statuscodes, die eine Integration betreffen, stehen stattdessen im API-Changelog.
Serverlizenzen
Der Agent wird pro Server lizenziert. Server sind ein eigener Pool und werden getrennt von den Domains des Hive-Plugins gezählt, eine Agent-Installation kostet Sie also nie eine Domain.
| Tarif | Server enthalten | Weitere Server |
|---|---|---|
| Free | keine | Nicht buchbar |
| Contributor | keine | Nicht buchbar |
| Professional | 1 | Beliebig viele |
| Business | 3 | Beliebig viele |
| Enterprise | nach Vertrag | nach Vertrag |
Eine weitere Lizenz kostet 4,90 € im Monat oder 49 € im Jahr pro Server, inkl. MwSt., und wird pro Server günstiger, je mehr es sind: 4,90 € für die ersten vier, 3,90 € ab der fünften, 2,90 € ab der zehnten, 1,90 € ab der fünfundzwanzigsten und 1,40 € ab der fünfzigsten. Der Volumen-Multiplikator von Business erhöht Ihre Domainzahl, nicht Ihre enthaltenen Server, denn die Server sind der Teil, der separat bezahlt wird.
Die Menge regeln Sie selbst unter Agent Servers in Ihrem Konto. Ein Host erscheint dort, sobald sein Agent die API zum ersten Mal aufruft, mit seiner Install-ID, seiner Version und dem Zeitpunkt, an dem er zuletzt gehört wurde. Hat das Konto eine Lizenz frei, nimmt der Host sie sofort. Hat es keine, sagt die Zeile das und ein Knopf fügt eine hinzu. Es gibt nichts vorher zu registrieren und nichts in eine Datei zu kopieren: der Host hält bereits einen API-Key Ihres Kontos, und das ist ein stärkerer Nachweis als jede Prüfdatei.
Die Identität ist die Install-ID, nie der Hostname und nie der Key. Den API-Key auf einem Host zu tauschen erzeugt keine zweite Lizenz, und die Maschine umzubenennen ändert nichts. Haben Sie mehr Agenten als Lizenzen, behalten die ältesten Hosts ihre. Eine gekündigte Serverlizenz funktioniert noch sieben Tage.
Was ohne Lizenz passiert
Nur eines hört auf: der Feed wird nicht mehr abgerufen. Alles andere läuft weiter, und das ist Absicht. Ein Server darf nicht ungeschützt werden, weil eine Rechnung liegen geblieben ist, und ein unlizenzierter Host ist kein wehrloser Host. Er bekommt lediglich die Community-Liste nicht mehr.
| Funktion | Ohne Lizenz |
|---|---|
| Feed-Download | Hört auf. Das ist der Teil, der bezahlt wird. |
| Die Liste, die schon im Kernel steht | Bleibt. Sie wird nie geleert und blockt weiter. |
| Lokale Erkennung | Läuft weiter. Alle dreizehn Quellen, alle Schwellwerte. |
| Lokales Blocken | Läuft weiter, samt Eskalation und samt Wiederherstellung nach einem Reboot. |
| Reports | Laufen weiter, im Tageslimit Ihres Tarifs. |
| Whitelist, Kette, Housekeeping, Log-Rotation | Laufen weiter. |
| Selbst-Update | Läuft weiter. Ein veralteter Agent auf einem unbezahlten Host ist unser Risiko, nicht unser Druckmittel. |
status | Zeigt den Lizenzstatus, den Grund, das Alter der Liste und was dagegen zu tun ist. |
Der Dienst wird nicht gestoppt, die Sets werden nicht geleert, lokale Sperren werden nicht aufgehoben, und im Log steht keine Werbung. Ein Free-Konto kann den Agenten daher als reinen Melder mit vollständigem lokalem Schutz betreiben, und das ist eine legitime Nutzung.
fail2ban ersetzen
Der Agent stellt sich nicht neben fail2ban, er übernimmt von ihm. fail2ban bleibt als eine Quelle unter vielen verfügbar, ein Host, der es noch betreibt, bekommt seine Sperren also weiter gemeldet. Ein Host ohne fail2ban verliert aber überhaupt nichts: für jede Angriffsart, die früher über ein Jail kam, liest jetzt ein Detektor das ursprüngliche Log.
Der Vergleich wurde gemessen und nicht behauptet. Über elf Tage auf einem Produktionshost fand der Agent 187 der 189 Adressen, die fail2ban auf derselben Maschine gesperrt hatte. Die zwei fehlenden waren von Hand eingespeiste Testadressen. Darüber hinaus meldete er 78 weitere Adressen, die tatsächlich angriffen und unter den Schwellwerten von fail2ban geblieben waren, und bei FTP traf er genau zu, drei von drei.
Zwei praktische Unterschiede. Die Eskalation für Wiederholungstäter kommt aus der eigenen
Bann-Historie des Agenten statt aus einem Jail, das das Log eines anderen Jails liest, und
reportedip-agent test <datei> tritt an die Stelle von
fail2ban-regex.
Zuerst prüfen, ob schon etwas diese Namen besitzt
Das hat auf einer Produktionsflotte einen Nachmittag gekostet, deshalb steht es vor allem anderen.
Ein handgeschriebenes Firewall-Skript der Art, wie diese Seite es früher dokumentiert hat, kann
genau die Namen benutzen, die der Agent benutzt. Vorgefunden wurden die Sets
rip-whitelist, rip-ssh, rip-mail, rip-web,
rip-ftp und rip-edge sowie eine Kette rip-blacklist, mit
-A INPUT -j rip-blacklist eingehängt, stündlich von einem Cronjob neu gebaut und
nahezu zeichengleich mit der Kette, die der Agent selbst aufbaut.
Auf so einem Host ist die übliche Reihenfolge in beide Richtungen falsch. Der erste Sync des Agenten
baut die Kette neu und ersetzt die bestehenden DROP-Regeln durch
LOG-Regeln, und damit ist der Host ungeschützt, bis der alte Cronjob wieder läuft, also
bis zu eine Stunde später. Und wenn dieser Job läuft, baut er die Kette auf seine Weise neu und
entfernt dabei die rip-local-Regel des Agenten. Zwei Programme, eine Kette, und jedes
hebt stündlich die Arbeit des anderen auf.
Prüfen Sie also vor dem ersten Sync, und wenn die Namen kollidieren, bleiben Sie auf diesem Host
nicht bei mode: log stehen. Installieren Sie den Agenten, was keine Regel anfasst,
übernehmen Sie die alte Whitelist, schalten Sie den alten Cronjob ab, und lassen Sie erst dann den
ersten Sync laufen, mit bereits gesetztem mode: drop.
# 1. Does something already own these names?
ipset list -n | grep "^rip-"
iptables -S INPUT | grep rip-
iptables -S rip-blacklist 2>/dev/null | head
crontab -l | grep -iE "ipset|blacklist|reportedip"
ls -l /etc/cron.d/ /etc/cron.hourly/ 2>/dev/null
# 2. If yes, take the old whitelist over FIRST. The feed can be
# downloaded again; that list cannot.
ipset list rip-whitelist | sed -n "/^Members/,\$p" | tail -n +2 > /tmp/rip-wl
ipset list rip-whitelist-v6 | sed -n "/^Members/,\$p" | tail -n +2 >> /tmp/rip-wl
wc -l /tmp/rip-wl
while read -r a; do
[ -n "$a" ] && reportedip-agent whitelist add "$a" "imported from the old script"
done < /tmp/rip-wl
reportedip-agent whitelist list | wc -l
# 3. Disable the old job, then hand the chain over in one step.
crontab -l | grep -v blacklist | crontab - # or: rm /etc/cron.d/<job>
sed -i "s/^mode: log/mode: drop/" /etc/reportedip-agent/config.yaml
reportedip-agent sync
reportedip-agent status
reportedip-agent whitelist list zurück.
Eine Weile beides betreiben
Beides zu betreiben ist gefahrlos und der sinnvolle Weg einer Migration. Der Agent schreibt nie nach
/etc/fail2ban, und fail2ban weiß nichts von rip--Sets, die zwei nutzen also
getrennte Ketten und getrennte Zustände. Zwei Regeln, die dieselbe Adresse verwerfen, kosten einen
Paketvergleich.
Das eine, was Sie nicht tun sollten, ist dasselbe Ereignis zweimal zu melden. Wenn Sie die fail2ban-Action, die Sperren über HTTP schickt, behalten und fail2ban als Agent-Quelle konfigurieren, verlässt jede Sperre den Host zweimal und wird zweimal aus Ihrem Tageskontingent bezahlt. Nehmen Sie den Agenten oder die Action.
# What did fail2ban ban, and what does the agent make of the
# same logs? Same file, same window, two verdicts.
fail2ban-client status sshd
reportedip-agent test /var/log/auth.log
# Per jail, then the agent over the file behind it
for j in $(fail2ban-client status | sed -n "s/.*Jail list:\t*//p" | tr -d " " | tr "," " "); do
echo "== $j"; fail2ban-client status "$j" | grep -E "Total banned|Currently banned"
done
reportedip-agent status | sed -n "/^sources:/,/^queue:/p"
fail2ban endgültig abschalten
Machen Sie das, wenn Sie die zwei ein paar Tage verglichen haben und die Quellenliste des Agenten jedes Jail abdeckt, das Sie hatten.
# 1. Stop it and keep it stopped.
systemctl stop fail2ban
systemctl disable fail2ban
# 2. Remove the fail2ban source from the agent config, then stop
# and start the daemon. A restart is not enough for a removed
# source: the daemon keeps tailing the old file.
$EDITOR /etc/reportedip-agent/config.yaml
systemctl stop reportedip-agent.service
systemctl start reportedip-agent.service
# 3. Check what fail2ban left in the kernel. Stopping it does not
# always clean up: a jail that once used an iptables action
# leaves old-style f2b- chains behind.
nft list tables | grep f2b || echo "no f2b table"
iptables -S | grep "f2b-" || echo "no f2b chain"
ipset list -n | grep f2b || echo "no f2b set"
# 4. Remove the leftovers from the RUNNING ruleset.
iptables -D INPUT -j f2b-sshd
iptables -F f2b-sshd && iptables -X f2b-sshd
# 5. And from the SAVED one, or they come back at the next boot.
grep -n "f2b" /etc/iptables/rules.v4 /etc/iptables/rules.v6
netfilter-persistent save
# 6. Confirm the agent is happy without it.
reportedip-agent status | grep -i fail2ban
reportedip-agent status; echo "exit $?"
f2b--Ketten nur
aus dem laufenden Ruleset löschen, stellt netfilter-persistent sie bei jedem Boot
aus /etc/iptables/rules.v4 und aus /etc/iptables/rules.v6
wieder her. Sie kommen leer zurück, verwerfen also nichts und sehen harmlos aus, und in einem
Jahr stehen sie noch da und verwirren den Nächsten, der das Ruleset liest. Prüfen Sie beide
Dateien: auf einem Host lagen die Reste nur in der v6-Datei, und wer allein
rules.v4 durchsucht, läuft daran vorbei. Erst das laufende Ruleset aufräumen, dann
speichern, und nach einem Reboot nachsehen.
Ein Rollback ist ein Befehl und dauert Sekunden, denn der Agent hat /etc/fail2ban nie
angefasst: systemctl enable --now fail2ban bringt jedes Jail und die eigene Tabelle
zurück, und der Agent bleibt davon unberührt. Auf einem Live-Host gemessen waren alle elf Jails nach
acht Sekunden wieder da.
Ressourcenverbrauch
Gemessen auf einem Debian-12-arm64-Host mit sieben Logdateien unter dem Agenten: 0,085 % eines Kerns und 16,6 MB resident belegter Speicher. Es gibt keinen Interpreter zu starten, keine Datenbank und kein Cache-Verzeichnis, das erst warm werden muss, und das ist der größte Teil der Erklärung für diese kleinen Zahlen.
Auf der Platte sind die eigenen Dateien des Agenten durch Konfiguration begrenzt und nicht durch
Hoffnung: log_max_mb mal log_keep plus die aktuelle Datei für das Log,
queue_max kleine Dateien für die Queue, und ein Bann-Speicher, der nur hält, was eine
Eskalation noch braucht. Das Statusverzeichnis eines belebten Hosts bleibt deutlich unter hundert
Megabyte, und deshalb greift die Standard-Plattengrenze von 200 MB auf einer gesunden Maschine nie.
Was der Agent nicht ist
Er ist kein Malware-Scanner, keine Web Application Firewall und kein Ersatz für Imunify360. Er liest Ihre Dateien nicht, untersucht keine Request-Bodies und stellt nichts in Quarantäne. Er blockt und meldet Adressen, und das tut er auf einer kleinen, prüfbaren Oberfläche. Für Schutz auf der Ebene einer einzelnen Anfrage auf einer WordPress-Site nehmen Sie stattdessen das Hive-Plugin. Die beiden laufen auf derselben Maschine, ohne sich zu stören.
Problembehebung
Ein Symptom, eine wahrscheinliche Ursache, ein Befehl. reportedip-agent doctor und
reportedip-agent status beantworten gemeinsam die meisten dieser Fälle, und es sind die
zwei Dinge, nach denen der Support zuerst fragt.
| Symptom | Ursache | Befehl |
|---|---|---|
| Startet nicht und nennt seine Config-Datei | Die Datei ist für Gruppe oder andere lesbar, und sie enthält Ihren API-Key. | chmod 0600 /etc/reportedip-agent/config.yaml && chown root:root /etc/reportedip-agent/config.yaml |
| Exit 2 mit „field ... not found in type" | Ein unbekannter Schlüssel in der Config. Der Parser ist absichtlich streng. | Den genannten Schlüssel entfernen oder korrigieren. Die Liste der gültigen Schlüssel steht oben. |
| Jeder Befehl endet nach einem Rollback mit Exit 2 | Die Binärdatei ist älter als die Config und kann einen neueren Block nicht lesen. | reportedip-agent update, der eine Befehl, der die Datei locker liest und die unbekannten Schlüssel nennt. |
| Die Sets existieren, sind aber leer | Entweder wurde der Feed abgelehnt oder die Liste ist an der Größenprüfung gescheitert. | reportedip-agent status sagt, welches von beidem, und die Zeile der Liste trägt den letzten Fehler. |
status sagt unlicensed | Das Konto hat für diesen Host keine Lizenz frei. | Eine unter Agent Servers hinzufügen. Die Liste im Kernel arbeitet in der Zwischenzeit weiter. |
| Es wird nie etwas gemeldet | Die Quelle, die gegriffen hätte, wurde nie erkannt, oder ihr Schwellwert wird nicht erreicht. | reportedip-agent test /pfad/zum/log, dann reportedip-agent status und den Abschnitt sources lesen. |
| Es wird nie etwas geblockt, obwohl Reports rausgehen | ban.enabled ist noch false, oder mode ist noch log. Zwei Schalter. | reportedip-agent ban list sagt in seinen letzten Zeilen, welches von beidem. |
| Gar kein Quellzustand vorhanden | Der Watch-Daemon ist nie gelaufen. | systemctl enable --now reportedip-agent.service |
Eine Quelle zeigt files=0 | Der Pfad oder Glob löst auf diesem Host auf nichts auf. | reportedip-agent doctor nennt die Quelle und das versuchte Muster. |
| Eine Log-Quelle gilt als unlesbar | Die Datei ist auch für root nicht lesbar. Meist ein Control Panel, das bei der Rotation Modus 000 setzt. | ls -l auf den Pfad, und die Rotation korrigieren, die das erzeugt hat. |
| Eine Quelle hat Treffer, meldet aber nie | Ihre Logzeitstempel sind mehr als eine Minute von der Systemuhr entfernt, das Zählfenster füllt sich also nie. | reportedip-agent doctor, die Drift-Zeilen unter sources. Die Zeitzone dieses Logs korrigieren. |
| Ihre eigene Adresse wurde gesperrt | Sie stand nicht auf der Whitelist. | reportedip-agent whitelist add <adresse>. Sofort wirksam, denn die Whitelist-Regel steht vor der Blockregel. |
Eine Sperre steht in bans.json, aber nicht im Kernel | Ein Reboot ohne Sync, oder ein Firewall-Reload, der das Set mitgenommen hat. | reportedip-agent sync stellt sie mit der Restzeit wieder her. |
Ein Kernel-Eintrag mit Datensatz none | Jemand hat mit ipset oder nft von Hand gesperrt, oder der Speicher ist verloren. Er läuft ab, aber kein Reboot bringt ihn zurück. | reportedip-agent ban list |
| Ein Set existiert mit falschem Typ oder ohne Timeout | Ein Überrest des dokumentierten Shell-Skripts oder eines anderen Werkzeugs. | ipset destroy <set> und danach reportedip-agent sync, das es korrekt neu anlegt. |
Beide Werkzeugketten haben rip--Objekte | Das Backend wurde ohne Migration gewechselt. | reportedip-agent sync --migrate-backend, und status gibt die genauen Entfernungsbefehle für die andere Seite aus. |
| Die Firewall ist nach einem Reboot weg | Ein gespeichertes Ruleset verweist auf ein rip--Set, und iptables-restore verwirft bei einem unbekannten Set die ganze Datei. | grep -n rip- /etc/iptables/rules.v4 /etc/iptables/rules.v6 und diese Zeilen entfernen. Der Agent braucht nichts Gespeichertes. |
| Eine entfernte Quelle wird weiter gelesen | Ein systemctl restart reicht für eine entfernte Quelle nicht. | systemctl stop reportedip-agent.service && systemctl start reportedip-agent.service |
| Reports hören auf, die Erkennung läuft weiter | Die Plattengrenze wurde erreicht. | Platz freimachen, dann reportedip-agent housekeeping. |
| HTTP 429 bei Reports | Das Tageslimit für Reports Ihres Tarifs. | Die Limits stehen unter Authentifizierung. |
| Die Queue wächst immer weiter | Der Sender ist nach einem Fehler pausiert, mit einem Backoff. | reportedip-agent status zeigt die Pause und den Grund; reportedip-agent report-queue schickt einen Durchlauf von Hand. |
| Jeder Web-Treffer ist dieselbe Handvoll Adressen | nginx sieht einen Proxy oder Cloudflare und nicht den Besucher. | set_real_ip_from konfigurieren. reportedip-agent install warnt genau vor diesem Fall. |
| „more addresses than the counter tracks at once" | Ein Scan, der breiter ist als der Zähler pro Quelle. Kein Fehler. | Nichts. Ein so breiter Scan ist ein Fall für die Community-Liste und nicht für lokale Sperren. |
status sagt, der Host sei bei den Versionen zurück | Das automatische Update kommt nicht durch, oder auto_update ist aus. | reportedip-agent update --check, dann reportedip-agent update. |
Zuletzt aktualisiert: · Betreut vom ReportedIP-Team