Log rotation

Ο daemon χειρίζεται και τα δύο τυπικά μοτίβα rotation:

  • Rotate-and-rename (το access log μετονομάζεται, ένα νέο αρχείο παίρνει τη θέση του). Ανιχνεύεται μέσω αλλαγής inode/device στη διαδρομή που παρακολουθεί ο daemon.
  • Copytruncate (το περιεχόμενο αντιγράφεται αλλού και μετά το πρωτότυπο μηδενίζεται). Ανιχνεύεται μέσω tell() > stat().

Σε οποιοδήποτε event ο daemon ανοίγει εκ νέου το αρχείο από την αρχή και γράφει info reopen after rotate dev=… ino=… (rotate-and-rename) ή info truncate file shrank (copytruncate) στο stderr.

Αν παρατηρήσεις εγγραφές που λείπουν γύρω από τη rotation, έλεγξε τη διαμόρφωση του εργαλείου rotation:

  • Στο OpenBSD newsyslog, η προεπιλεγμένη rotation είναι rotate-and-rename — δεν χρειάζεται ειδική διαμόρφωση.
  • Στο Linux logrotate, προτίμησε το default (rotation και SIGHUP στον web server) έναντι του copytruncate mode. Και τα δύο δουλεύουν, αλλά το rotate-and-rename είναι πιο φθηνό και δεν χάνει γραμμές.

Script rc.d (OpenBSD)

Ελάχιστο /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 $1

Έπειτα:

doas rcctl enable abusive_http_watch
doas rcctl start abusive_http_watch
doas rcctl check abusive_http_watch

Στο Linux με systemd, βλέπε την τεκμηρίωση της διανομής σου· μια απλή Type=simple unit που δείχνει στο /usr/local/sbin/abusive_http_watch με τα ίδια ορίσματα αρκεί.

Events syslog

Ο daemon εκπέμπει μια κλάση event — added — όταν μια νέα IP ξεπερνά το κατώφλι hits. Μορφή:

<syslog-tag>[<pid>]: added ip=<ip> path=<διαδρομή-blocklist>

Παράδειγμα:

abusive_http_watch[12345]: added ip=198.51.100.42 path=/var/www/run/abusive_http_hosts

Δρομολόγηση μέσω syslog.conf σε αφιερωμένο αρχείο για αναθεώρηση:

local0.notice                                          /var/log/abusive_http.log

Σε συνδυασμό με ABUSIVE_SYSLOG_FACILITY=local0, δίνει ένα καθαρό audit log κάθε μπλοκαρισμένης IP.

Σήματα παρακολούθησης

Για αυτοματοποιημένη παρακολούθηση, δύο χρήσιμοι δείκτες:

  • Ρυθμός αύξησης blocklistwc -l /var/www/run/abusive_http_hosts στον χρόνο. Σε δημόσιο web server, αυτό θα πρέπει να αυξάνεται σταθερά (αρκετές IP ανά ημέρα έως πολλές ανά ώρα, ανάλογα με την έκθεση). Μια 24ωρη σταθεροποίηση σε δημόσιο site υποδηλώνει ότι ο daemon δεν τρέχει ή διαβάζει λάθος log.
  • Υγεία διεργασίας — Το pgrep -f abusive_http_watch θα πρέπει πάντα να επιστρέφει ένα PID. Συναγερμός αν μηδέν.

Για συστήματα με Prometheus, ένας μικρός exporter που απλώς κάνει wc -l στο αρχείο blocklist και εκθέτει το μέτρημα ως gauge είναι αρκετός. Δεν υπάρχει metrics endpoint στον ίδιο τον daemon — εκ σχεδιασμού, για να παραμένει χωρίς εξαρτήσεις.

Troubleshooting

Το αρχείο blocklist παραμένει άδειο

Πιθανές αιτίες, κατά σειρά πιθανότητας:

  1. Ο daemon διαβάζει λάθος αρχείο. Τρέξε σε πρώτο πλάνο με ABUSIVE_DEBUG=1. Επιβεβαίωσε ότι λογάρει start following dev=… ino=… για την αναμενόμενη διαδρομή. Αν όχι, διόρθωσε το όρισμα.
  2. Καμία πραγματική κίνηση επίθεσης. Απίθανο σε δημόσιο web server, πιθανό σε εσωτερικό. Τρέξε με ABUSIVE_DEBUG=1 και ψάξε για γραμμές [dbg] ip=… χωρίς αντίστοιχο [dbg] token match.
  3. Η whitelist καταπίνει τα πάντα. Έλεγξε το /etc/abusive_http_whitelist — μια ξεχασμένη /0 CIDR εγγραφή whiteliστάρει ολόκληρο το internet. Αφαίρεσε και επανεκκίνησε.
  4. Πολύ ψηλό κατώφλι hits. Χαμήλωσε προσωρινά το ABUSIVE_MIN_HITS σε 1 και παρατήρησε.

Η blocklist μεγαλώνει αλλά το firewall δεν μπλοκάρει

Ο daemon γράφει το αρχείο. Το firewall πρέπει να ενημερωθεί να το διαβάσει. Έλεγξε:

  • Ο cron επαναφορτώνει τον πίνακα pf / το set nftables κάθε λίγα λεπτά (ο daemon δεν καλεί τον pfctl από μόνος του).
  • Ο firewall κανόνας που αναφέρεται στον πίνακα είναι στη σωστή chain και αρκετά quick ώστε να ενεργήσει πριν από οποιονδήποτε μεταγενέστερο κανόνα pass.

Νόμιμοι χρήστες μπλοκάρονται

Πρόσθεσε τη δημόσια IP τους ή το CIDR range τους στο /etc/abusive_http_whitelist. Ο daemon ξαναδιαβάζει τη whitelist σε κάθε γραμμή — οι αλλαγές ενεργοποιούνται σε δευτερόλεπτα.

Για να αφαιρέσεις μια μεμονωμένη IP από την υπάρχουσα blocklist, ξαναγράψε το αρχείο απευθείας και επαναφόρτωσε τον firewall πίνακα. Ο daemon δεν χρειάζεται επανεκκίνηση — απλώς δεν θα ξαναπροσθέσει την IP εκτός αν ο χρήστης ξανατυρμοδοτήσει tokens.

Ο daemon crashάρει μετά από log rotation

Δεν θα έπρεπε να συμβαίνει δεδομένου του χειρισμού rotation που περιγράφεται παραπάνω. Αν συμβαίνει, τρέξε σε πρώτο πλάνο με ABUSIVE_DEBUG=1, προκάλεσε rotation και κατάγραψε το stderr. Στείλε το καταγεγραμμένο output μέσω της σελίδας Επικοινωνία — αυτό είναι πραγματικό bug που αξίζει να διορθωθεί.

Καθαρός τερματισμός

Ο daemon παρακολουθεί το SIGTERM και βγαίνει καθαρά μετά την τρέχουσα επανάληψη:

doas rcctl stop abusive_http_watch

Λογάρει [info] TERM received, exiting, κλείνει το logfile handle, flushάρει τυχόν εκκρεμείς εγγραφές και βγαίνει με status 0. Καμία αλλοίωση κατάστασης, ακόμη και σε ένα πολυάσχολο log.