Operacje
Rotacja logów
Daemon obsługuje oba popularne wzorce rotacji:
- Rotate-and-Rename (access-log zostaje przemianowany, nowy plik zajmuje jego miejsce). Wykrywane przez zmianę inode/device na obserwowanej ścieżce.
- Copytruncate (zawartość pliku jest kopiowana gdzie indziej, potem oryginał obcięty do rozmiaru zero). Wykrywane przez
tell() > stat().
W obu przypadkach daemon otwiera plik na nowo od początku i zapisuje info reopen after rotate dev=… ino=… (Rotate-and-Rename) lub info truncate file shrank (Copytruncate) na stderr.
Jeśli wokół rotacji brakuje wpisów, sprawdź konfigurację narzędzia rotacji:
- Na OpenBSD
newsyslogstandardową rotacją jest Rotate-and-Rename — żadna specjalna konfiguracja nie jest potrzebna. - Na Linuksie
logrotatelepiej brać default (rotacja + SIGHUP do serwera web) zamiast trybucopytruncate. Oba działają, ale Rotate-and-Rename jest tańszy i nie traci linii.
Skrypt rc.d (OpenBSD)
Minimalny wariant /etc/rc.d/abusive_http_watch:
#!/bin/ksh
daemon="/usr/local/sbin/abusive_http_watch"
daemon_flags="/var/www/logs/access.log"
daemon_user="_www"
. /etc/rc.d/rc.subr
rc_bg=YES
rc_reload=NO
rc_cmd $1Potem:
doas rcctl enable abusive_http_watch
doas rcctl start abusive_http_watch
doas rcctl check abusive_http_watchNa Linuksie z systemd patrz dokumentacja dystrybucji; prosta jednostka Type=simple wskazująca na /usr/local/sbin/abusive_http_watch z tymi samymi argumentami wystarcza.
Eventy syslog
Daemon emituje jedną klasę eventów — added — gdy nowe IP przekracza próg trafień. Format:
<syslog-tag>[<pid>]: added ip=<ip> path=<ścieżka-blocklisty>Przykład:
abusive_http_watch[12345]: added ip=198.51.100.42 path=/var/www/run/abusive_http_hostsPrzez syslog.conf zrutować do osobnego pliku do przeglądu:
local0.notice /var/log/abusive_http.logW połączeniu z ABUSIVE_SYSLOG_FACILITY=local0 daje to czyste audit-log każdego zablokowanego IP.
Sygnały monitoringu
Dla zautomatyzowanego monitoringu dwa wskaźniki są użyteczne:
- Tempo wzrostu blocklisty —
wc -l /var/www/run/abusive_http_hostsw czasie. Na publicznym serwerze web to powinno stale rosnąć (od kilku IP dziennie do wielu na godzinę, zależnie od ekspozycji). Płaska linia przez 24 h na publicznej stronie wskazuje, że daemon nie działa lub czyta zły log. - Health procesu —
pgrep -f abusive_http_watchpowinno zawsze zwracać dokładnie jedną PID. Alert przy zero.
Dla setupów Prometheus wystarczy maleńki eksporter, który po prostu robi wc -l na pliku blocklisty i eksponuje liczbę jako gauge. Bez metrics-endpointu w samym daemonie — by design, aby utrzymać go bez zależności.
Troubleshooting
Plik blocklisty pozostaje pusty
Możliwe przyczyny, według prawdopodobieństwa:
- Daemon czyta zły plik. Uruchomić na pierwszym planie z
ABUSIVE_DEBUG=1. Sprawdzić, czy logujestart following dev=… ino=…dla oczekiwanej ścieżki. Jeśli nie, poprawić argument. - Brak prawdziwego ruchu ataków. Mało prawdopodobne na publicznym serwerze web, ale możliwe wewnętrznie. Uruchomić z
ABUSIVE_DEBUG=1i szukać linii[dbg] ip=…bez odpowiadającego[dbg] token match. - Whitelist pochłania wszystko. Sprawdzić
/etc/abusive_http_whitelist— błędny wpis CIDR/0whitelistuje cały internet. Usunąć i zrestartować. - Próg trafień zbyt wysoki. Testowo obniżyć
ABUSIVE_MIN_HITSdo1i obserwować zachowanie.
Blocklista rośnie, ale firewall nie blokuje
Daemon pisze plik. Firewall musi zostać poinstruowany, aby go czytał. Sprawdzić:
- Cron przeładowuje tabelę
pf/ setnftablesco kilka minut (daemon nie wywołujepfctlsam). - Reguła firewalla, która wskazuje na tabelę, jest w odpowiednim chain i
quickna tyle, aby chwytać przed późniejszymi regułamipass.
Legalni użytkownicy są blokowani
Dodać ich publiczny IP lub CIDR-range do /etc/abusive_http_whitelist. Daemon czyta whitelistę przy każdej linii — zmiany działają w ciągu sekund.
Aby usunąć pojedyncze IP z istniejącej blocklisty, edytować plik bezpośrednio i przeładować tabelę firewalla. Daemon nie potrzebuje restartu — wpisze IP ponownie tylko wtedy, gdy użytkownik znowu trafi w tokeny.
Daemon crashuje po rotacji logów
Nie powinno się wydarzyć z opisaną wyżej obsługą rotacji. Jeśli jednak tak, uruchomić na pierwszym planie z ABUSIVE_DEBUG=1, wywołać rotację i zapisać stderr. Zapisany log wysłać przez stronę
Kontakt — to prawdziwy bug, który chcemy naprawić.
Czysty shutdown
Daemon łapie SIGTERM i kończy czysto po aktualnej iteracji:
doas rcctl stop abusive_http_watchLoguje [info] TERM received, exiting, zamyka handle pliku logu, flushuje wszystkie oczekujące write’y i kończy ze statusem 0. Bez korupcji stanu, nawet przy mocno używanym logu.