Erkennung und Regeln
Was der Agent in den Logs findet, die ein Server ohnehin schreibt: die vierzehn Quelltypen und ihre Schwellwerte, wie eine Quelle nachgetragen wird, die der Installer nicht fand, was die Maschine verlässt und was sie nie verlässt, und die Regeldateien, aus denen jeder Erkenner besteht, auch die, die Sie selbst schreiben.
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 vierzehn 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. |
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 den Nameserver eines anderen 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 getroffenen Daten, 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 | das Journal der Unit, sonst /var/log/fail2ban.log | 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. |
scan | das Kernel-Journal (journalctl -k), sonst /var/log/kern.log oder /var/log/messages | Die Zeilen der Port-Scan-Regel, die der Sync-Lauf mit dieser Quelle anlegt: ein SYN auf einen Port, auf dem dieser Host nicht lauscht, mit dem Präfix rip-scan:. Zehn Anfragen in zehn Minuten von einer Adresse sind ein Scan. Nichts in einer Kernel-Log-Zeile stammt von der Gegenstelle. Siehe unten. |
web-app ist kein Quelltyp und kann nicht in sources geschrieben werden. Es
ist ein zweiter Erkenner, der auf den Zeilen läuft, die eine web-Quelle schon liest, und
er hat seinen eigenen Schwellwert, deshalb steht er in der Schwellwert-Tabelle weiter oben unter
seinem eigenen Namen. Ein Agent, dessen Konfiguration ihn nennt, startet nicht: sources[0]: type "web-app" is not supported in this version.
Port-Scans, aus dem Kernel-Log
Jede andere Quelle liest ein Log, das ein Dienst schreibt. Die Quelle scan liest den
Kernel, und sie ist die eine Quelle, die auch die Firewall verändert: steht sie in der Config, legt
der Sync-Lauf hinter den Listen eine Regel an, die ein SYN auf einen Port protokolliert, auf dem
dieser Host nicht lauscht, mit dem Präfix rip-scan: und nach einem ersten Schub von 20
höchstens zehn Zeilen je Minute, damit ein Scan aller 65535 Ports das Journal nicht flutet. Mit dem ipset-Backend ist das
eine eigene Kette, rip-blacklist-scan, mit nftables eine Regel in der Kette. Die
lauschenden Ports werden bei jedem Sync aus /proc gelesen, ein Dienst, den Sie starten,
ist nach dem nächsten Lauf also kein Scan-Ziel mehr, und es gibt nichts zu deklarieren. Als lauschend
zählt nur ein Socket, den von außen etwas erreichen könnte. Ein Port, der allein auf
127.0.0.1 oder ::1 gebunden ist, bleibt in der Regel, denn ein Paket, das
dort aus dem Netz eintrifft, ist die Probe auf einen geschlossenen Port und sonst nichts.
Die Liste aus dem letzten Sync ist nicht die einzige Prüfung: Die Regel fragt beim Eintreffen des Pakets auch den Kernel, und ein SYN auf einen Port, auf dem in diesem Moment ein Socket lauscht, ist eine Verbindung und wird nie geloggt. Das deckt einen Dienst ab, der seit dem letzten Sync gestartet wurde, und einen Daemon, der einen Port nur für eine einzelne Übertragung öffnet. Den Passivbereich eines laufenden FTP-Servers (pure-ftpd, proftpd, vsftpd) liest der Sync aus dessen Konfiguration und nimmt ihn aus der Regel heraus; läuft der Server ohne konfigurierten Bereich, bleibt stattdessen der ephemere Portbereich des Kernels außen vor. Ein Kernel ohne Socket-Match behält die Regel ohne diese Prüfung.
Die Regel steht hinter der Whitelist und hinter den Listen. Eine Adresse auf Ihrer Whitelist hat
die Kette vorher verlassen und erzeugt keine Zeile, und eine Adresse, die die Listen ohnehin
verwerfen, erreicht sie ebenfalls nicht. In mode: log und mode: off tut
sie das, was alles andere in diesen Modi tut.
Die Quelle liest das Kernel-Journal, journalctl -k, und weicht auf
/var/log/kern.log oder /var/log/messages aus, wo es kein Journal gibt;
ein gesetzter path gewinnt. Die gelieferte Regel scan zählt zehn Anfragen
in zehn Minuten von einer Adresse, meldet sie unter Kategorie 14 (Port Scan) als
port probes und sperrt die Adresse wie jeden anderen Fund. Ein Client, der einen
geschlossenen Port wiederholt anfragt, schickt höchstens sechs Pakete, deshalb liegt die Schwelle
bei zehn. install schreibt die Quelle auf einem frischen Host als letzten Eintrag unter
sources; ein früher installierter Host behält seine Konfiguration, und das Nachtragen
ist eine Zeile, gefolgt von einem Neustart des Watch-Dienstes und einem Sync für die Regel.
# config.yaml: the source, next to the ones the installer wrote
sources:
- type: sshd
- type: scan
# /etc/reportedip-agent/rules.d/50-scan.yaml: ban a scanner on this
# host, but leave the report to hosts that see more of it. Every field
# not named here stays as shipped.
format: 1
rules:
- id: scan
action: {ban: true, report: false}
# The same file with enabled: false switches the rule off; the firewall
# rule and its log lines stay. A threshold of your own goes into
# config.yaml and wins over the file:
thresholds:
scan: {hits: 20, window_minutes: 10}
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, lassen Sie reportedip-agent test über die Datei laufen, starten dann den
Watch-Dienst neu und schauen in status: der Abschnitt sources zeigt Treffer
pro Quelle. doctor zeigt je Quelle einen Wert files=, und eine Quelle mit
dem Wert null findet keine einzige Datei.
Was die Maschine verlässt
Ein Report enthält die Adresse, die IDs der Threat Categories und einen generierten Satz. Keine Logzeile, kein Request-Body, kein User-Agent, keine URL und kein Benutzername wird je übertragen, ein Report kann also auch aus Versehen nicht Ihre Kunden, Ihre Pfade oder Ihre Zugangsdaten verraten.
Eine Präzisierung, denn eine absolute Zusage wäre hier falsch. Zwei Quellen setzen einen Namen aus
dem Log in diesen generierten Satz: bei fail2ban den Namen des Jails, das gesperrt hat,
bei imunify360 den Namen der Regel, die gegriffen hat. Beide werden auf Buchstaben,
Ziffern, Punkt, Bindestrich und Unterstrich gefiltert und auf 32 Zeichen gekürzt, bevor sie die
Maschine verlassen, denn ein Jail-Name stammt aus einer Logzeile und ist damit angreifernahe
Eingabe. Keine andere Quelle schickt überhaupt etwas aus einer Logzeile.
Der Hostname wird mitgesendet, und das nur zu einem Zweck: damit Sie Ihre eigene Maschine in der
Serverliste wiedererkennen, statt Zufallskennungen zu vergleichen. Er wird auf dem Client auf
A-Za-z0-9._- gefiltert, alles andere wird entfernt und nicht ersetzt, auf 191 Zeichen
gekürzt, und er geht nie ohne die Install-ID daneben hinaus.
Die Identität ist weiterhin die Install-ID. Der Hostname ist eine Bezeichnung und nichts weiter: die Maschine umzubenennen ändert nichts an der Lizenz, nichts daran, welcher Host sie hält, und nichts an dem, was der Server entscheidet. Sie können zusätzlich in Ihrem Konto ein eigenes Label vergeben; es steht vor dem Hostnamen 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.
Regeln
Eine Regel sagt, welche Zeilen einer Quelle Treffer sind, wo in so einer Zeile die Adresse steht, wie ein Treffer heißt und wie viele davon in wie vielen Minuten zu einer Sperre oder einer Meldung werden. Jeder Detektor des Agenten ist eine Regel, und jede Regel ist eine Datei. Drei Ebenen werden gelesen und über die Regel-ID zusammengeführt:
| Ebene | Wo sie liegt | Was sie ist |
|---|---|---|
| 1 | In der Binärdatei | Die mitgelieferten Regeln, eine Datei je Quelltyp. Sie laufen aus der Binärdatei. Nach dem nächsten Sync liegt eine Kopie zum Lesen unter /var/lib/reportedip-agent/rules.d/standard/; eine Änderung dort überschreibt der Sync danach wieder. install legt dieses Verzeichnis und daneben packs/ schon leer an, damit die drei Ebenen sichtbar sind, bevor der erste Sync zwei davon füllt. |
| 2 | Ein signiertes Regelpaket von reportedip.com | Der Sync-Lauf holt es, prüft seine Signatur gegen einen in die Binärdatei eingebauten Schlüssel, bevor ein einziges Byte davon als Regel gelesen wird, und bewahrt es im State-Verzeichnis auf. Ein Host, der den Dienst nicht erreicht, behält das Paket, das er hat. Ein Paket, dessen Signatur nicht stimmt, wird abgewiesen, und das vorhandene auf der Platte bleibt. |
| 3 | /etc/reportedip-agent/rules.d/*.yaml | Ihre Dateien: Überschreibungen mitgelieferter Regeln und eigene Regeln. |
Das Paket gewinnt über die Binärdatei, Ihre Dateien gewinnen über das Paket. Eine Überschreibung
nennt eine Regel über ihre id und nur die Felder, die sich ändern; jedes Feld, das sie
nicht nennt, behält den Wert der Ebene darunter. match und examples werden
als Ganzes ersetzt, action Feld für Feld. enabled: false schaltet eine
Regel ab. Der Dateiname spielt keine Rolle: eine Datei namens 10-sshd.yaml unter
rules.d verdeckt nicht die mitgelieferte Datei dieses Namens, sie wird wie jede andere
gelesen und über die IDs darin zusammengeführt, ein Release, das eine mitgelieferte Datei umbenennt,
kann aus Ihrer Überschreibung also kein Duplikat machen.
Das Dateiformat
Eine Datei enthält beliebig viele Regeln. Das hier ist eine vollständige, aus der Testsuite des Agenten selbst:
format: 1
rules:
- id: my-sshd
source: sshd
match:
regex: '(Failed password|Invalid user) .* from '
anchors: ["Failed password", "Invalid user", "Accepted "]
reset: 'Accepted (password|publickey) for .* from '
addr: {after: " from ", occurrence: last}
categories: [22, 18]
noun: failed logins
threshold: {hits: 5, window_minutes: 10}
examples:
match:
- {line: "Sep 24 14:47:38 host sshd[1]: Failed password for root from 45.33.32.156 port 51422 ssh2", addr: 45.33.32.156}
inject:
- {line: "Sep 24 14:47:38 host sshd[1]: Invalid user x from 8.8.8.8 port 22 from 45.33.32.156 port 51422", addr: 45.33.32.156}
nomatch:
- "Sep 24 14:47:38 host sshd[1]: Connection closed by 45.33.32.156 port 1"
| Feld | Bedeutung | Was der Lader prüft |
|---|---|---|
format | Die erste Zeile jeder Regeldatei. Dieser Agent liest Format 1. | Eine Datei mit einer höheren Nummer wurde für einen neueren Agenten geschrieben und wird übersprungen; eine Datei ohne die Zeile ebenso. |
id | Der Name der Regel, so wie rules list und das Journal ihn zeigen. | a-z, 0-9 und - ab dem zweiten Zeichen, höchstens 32 Bytes. Eine ID, die in einer tieferen Ebene schon existiert, macht die Regel zur Überschreibung. |
source | Der Quelltyp, dessen Zeilen die Regel liest, einer der vierzehn: sshd, fail2ban, web, web-error, postfix, dovecot, exim, ftp, named, panel, modsec, csf, imunify360, scan. | Pflicht für eine neue Regel. |
event | Die Event-Quelle, unter der die Treffer zählen, also der Name, auf den sich ein Eintrag unter thresholds in der config.yaml bezieht, und der Name im Kommentar einer Meldung. Voreinstellung ist die ID. | Derselbe Zeichensatz wie eine ID. Regeln mit derselben Event-Quelle teilen sich deren Schwellwert, und ein Treffer zählt einmal, egal welche von ihnen ihn gefangen hat. Eine eigene Regel kann die Event-Quelle einer mitgelieferten Regel nicht übernehmen: überschreiben Sie stattdessen diese Regel über ihre ID. |
enabled | true oder false; ein fehlender Schlüssel heißt true. | enabled: false in einer Überschreibung schaltet eine mitgelieferte Regel ab, ohne ihre Datei anzufassen. |
match.regex | Das Muster, das entscheidet, ob eine Zeile ein Treffer ist, und sonst nichts. RE2-Syntax, so wie Go sie liest. | Höchstens 512 Bytes. Keine Flags wie (?i), (?s) oder (?m), keine benannten Gruppen: die Adresse kommt nicht aus dem Muster. |
match.anchors | Wörtliche Zeichenfolgen, die jeder Treffer enthält. Das Muster läuft nur auf einer Zeile, die eine davon enthält; jede andere Zeile erreicht es nie. | Pflicht. Jeder Anker mindestens 6 Bytes und wörtlich Teil von regex oder reset. Ist reset gesetzt, muss mindestens ein Anker darin vorkommen, sonst greift der Reset nie. |
match.ignore | Muster, die eine Zeile verwerfen, bevor regex sie sieht. | RE2, dieselben Grenzen wie regex. |
match.reset | Das Muster einer Zeile, die den Zähler einer Adresse löscht, ein erfolgreicher Login. | RE2, dieselben Grenzen. Die Adresse wird genauso gelesen wie bei einem Treffer. |
match.builtin | Statt eines Musters der Name eines kompilierten Detektors. Die mitgelieferten Regeln für web, web-app, web-error, modsec, exim, panel, named, fail2ban, csf und imunify360 sind von dieser Art und tragen nur die Policy. | Nicht zusammen mit regex, und ohne anchors, ignore, reset, addr oder examples. |
addr | Wo in einer passenden Zeile die Adresse steht. Genau eine Form: after mit occurrence: last oder first; between: [left, right]; in_brackets: N, das N-te [...], gezählt ab 1; before_byte: ":", ein Byte; field: N, das N-te durch Leerraum getrennte Feld, gezählt ab 0. Ein optionales upto: "<" schneidet die Zeile am ersten Vorkommen dieser Marke ab, bevor die Form angewendet wird, ein Feld, das die Gegenseite dahinter schreibt, ist damit unerreichbar. | Pflicht für eine Regex-Regel. after braucht mindestens 3 Bytes und eine occurrence; upto hat höchstens 16 Bytes. |
categories | Die IDs der Threat Categories, die eine Meldung trägt. Es gibt 63, nummeriert von 1 bis 63. | Pflicht, wenn die Regel meldet. Jede mindestens 1. |
noun | Wie ein Treffer im Kommentar einer Meldung heißt, etwa failed logins. | Buchstaben, Ziffern und Leerzeichen, höchstens 40. |
threshold | hits innerhalb von window_minutes, das Paar, das ein fail2ban-Jail maxretry und findtime nannte. | hits 1 bis 10000, window_minutes 1 bis 1440. Ohne den Block gelten min_hits und window_minutes aus der config.yaml. Ein Eintrag unter thresholds in der config.yaml gewinnt über beides. |
action | ban und report, jeweils true oder false; beide sind true, wenn sie fehlen. | Beide false wird abgewiesen: eine Regel, die nichts tut, wird stattdessen mit enabled: false abgeschaltet. |
examples | Die Tests der Regel. match: Zeilen und die Adresse, die jede liefert. inject: Zeilen mit einer zweiten, untergeschobenen Adresse in einem Feld, das die Gegenseite schreibt, und die Adresse, die die Regel trotzdem liefern muss. nomatch: Zeilen, die die Regel nicht treffen darf. | Pflicht für eine Regex-Regel, mindestens eine je Art, und mindestens eine nomatch-Zeile muss eine Adresse enthalten. Sie laufen bei jedem Laden der Regel; eine Regel, deren Beispiele nicht aufgehen, lädt nicht. |
Warum die Adresse keine Capture-Gruppe ist
fail2ban hatte das zweimal, CVE-2013-2178 und CVE-2009-0362, und beide Male war es derselbe Fehler:
die Adresse kam aus dem Muster, und ein Angreifer hatte eine Adresse seiner Wahl in ein Feld
geschrieben, das das Muster erreichte. RE2 findet den am weitesten links stehenden Treffer, in
Invalid user x from 8.8.8.8 port 22 from 45.33.32.156 port 51422 würde eine Gruppe
hinter dem ersten from also 8.8.8.8 sperren, und das ist der Benutzername,
den der Angreifer getippt hat. addr: {after: " from ", occurrence: last} nimmt das
letzte, das, das sshd selbst geschrieben hat. Darum nennt eine Regel eine Position statt einer
Gruppe, und darum trägt jede Regel eine inject-Zeile, die das beweist.
Was Sie vor Ihrer eigenen Regel schützt
Die Beispiele laufen bei jedem Laden der Regel, ein Muster, das seine eigenen Zeilen nicht mehr
trifft, lädt also nicht. Eine Musterregel, die Ihre Ebene hinzufügt oder überschreibt, sperrt in den ersten 24 Stunden ihres Inhalts
und meldet nicht (eine Regel mit match.builtin nie): ein falscher Kernel-Eintrag läuft ab und steht in ban list, eine
falsche Meldung lässt sich nicht zurücknehmen. rules status markiert so eine Regel als
young. Ein Neustart des Daemons beginnt den Tag von vorn.
Zwei Wächter beobachten eine Regel im Betrieb. Erreichen drei Adressen aus Ihrer Whitelist innerhalb von zehn Minuten ihren Schwellwert, liest die Regel das falsche Feld, denn echte Angreifer stehen nie auf der Whitelist; sie meldet dann nicht mehr, bis ihre Datei sich ändert, sperrt aber weiter, und davor schützt die Whitelist. Schiebt eine junge Regel innerhalb einer Minute mehr als 50 verschiedene Adressen über ihren Schwellwert, trifft sie jeden Besucher und wird ganz ausgesetzt, Sperren und Meldungen, bis ihr Inhalt sich ändert. Eine etablierte Regel wird für einen Ansturm nie ausgesetzt: ein verteilter Brute-Force-Angriff mit Hunderten Quellen pro Minute ist genau das, wofür eine sshd-Regel da ist. Eine Regel aus dem Paket beobachtet der Ansturm-Wächter wie eine junge, weil ein Paket alle Hosts auf einmal erreicht.
Ein Eintrag unter thresholds in der config.yaml gewinnt weiter über die Datei, ein Host,
den Sie eingestellt haben, verliert also nichts. Eine Datei, die kein gültiges YAML ist oder ein
neueres Format nennt, wird allein übersprungen, die anderen laden. Eine Regel, die an einer der
Prüfungen oben scheitert, kostet Ihre ganze Ebene: die mitgelieferten Regeln und das Paket laufen
weiter, status und doctor sagen es, und rules check nennt
Datei, Zeile und ID.
Die rules-Befehle
reportedip-agent rules list # every rule: id, source, event, kind, state, threshold, action
reportedip-agent rules show sshd # one rule as merged, and whether it is overridden
reportedip-agent rules check # load rules.d the way the daemon does, and say what is wrong
reportedip-agent rules check /root/my.yaml # try a file before it is put in place
reportedip-agent rules export sshd # print the shipped file of a rule, as the template
reportedip-agent rules status # state, hits since the daemon started, young and suspended rules
reportedip-agent rules disable sshd # write enabled: false for one id; enable takes it back
reportedip-agent test --rule my-sshd /var/log/auth.log # run one rule alone over a real log
list, show, check, export und
status lesen und geben aus. check ohne Datei lädt Ihr Verzeichnis genau
so, wie der Daemon es täte; mit Dateien lädt es stattdessen diese über den mitgelieferten Regelsatz, eine
Datei lässt sich also prüfen, bevor sie in rules.d liegt. export gibt die
mitgelieferte Datei aus, in der eine Regel steht, mit Kommentaren, als Ausgangspunkt einer
Überschreibung. enable und disable sind die beiden, die schreiben: eine
einzige generierte Datei, 90-agent-toggles.yaml, nur für root zugänglich, bei jedem Aufruf neu
geschrieben. test --rule lässt nur diese eine Regel laufen und keinen kompilierten
Detektor daneben, nimmt den Quelltyp aus der Regel und meldet und sperrt nichts, wie
test immer.
Eine eigene Regel anlegen
- Mit einer mitgelieferten Datei anfangen.
reportedip-agent rules export sshd > /root/60-sshd.yamlgibt die Datei aus, in der die Regel steht, mit Kommentaren und Beispielen. - Kürzen, oder eine neue ID vergeben. Für eine Überschreibung bleiben die
idund nur die Felder, die sich ändern; die Datei unten ist vollständig. Für eine eigene Regel vergeben Sie eine neueidmitsource,match,addr,categoriesundexamples, wiemy-sshdoben. Eine neue ID ist eine neue Event-Quelle, die mitgelieferte Regel läuft daneben weiter. - Prüfen.
reportedip-agent rules check /root/60-sshd.yamllädt die Datei über den mitgelieferten Regelsatz genau so, wie der Daemon es täte, und gibt jedes Problem mit Datei, Zeile und ID aus, oder eine Zeile, die ok sagt. - Ablegen.
install -m 644 -o root -g root /root/60-sshd.yaml /etc/reportedip-agent/rules.d/. Das Verzeichnis und jede Datei darin müssen root gehören und für niemanden sonst beschreibbar sein, und ein Symlink, der aus dem Verzeichnis hinauszeigt, wird abgewiesen; sonst wird die ganze Ebene nicht benutzt. - Eine Minute warten. Der Daemon übernimmt die Änderung von selbst, ohne Neustart,
und die Zähler beginnen von vorn.
reportedip-agent rules statuszeigt die Regel, am ersten Tag als young markiert.reportedip-agent test --rule my-sshd /var/log/auth.logzeigt derweil, was sie gefangen hätte.
# /etc/reportedip-agent/rules.d/60-sshd.yaml: the shipped sshd rule,
# stricter on this host. Everything not named here stays as shipped.
format: 1
rules:
- id: sshd
threshold: {hits: 3, window_minutes: 10}
Zuletzt aktualisiert: · Betreut vom ReportedIP-Team