Το Fail2ban εγκαθίσταται πρώτο και συνήθως εκεί σταματά η υπόθεση: το πακέτο μπήκε, η υπηρεσία τρέχει, το sshd φαινομενικά καλύπτεται. Έξι μήνες αργότερα αποδεικνύεται ότι το jail διαβάζει ένα αρχείο που δεν υπάρχει σε αυτό το σύστημα και ότι όλα τα υπόλοιπα — το ταχυδρομείο, ο πίνακας ελέγχου, η φόρμα σύνδεσης του ιστότοπου — δεν καλύφθηκαν ποτέ.

Ας δούμε τι αξίζει να ενεργοποιηθεί σε ένα συνηθισμένο VPS με ιστότοπο, ποιους αριθμούς να βάλετε και πώς να βεβαιωθείτε ότι ένα jail δουλεύει αντί απλώς να υπάρχει στη ρύθμιση.

Πρώτα ελέγξτε αν το sshd πιάνει κάτι

Μία εντολή:

sudo fail2ban-client status sshd

Η έξοδος έχει γραμμές για Currently failed, Total failed και Total banned. Αν το Total failed είναι μηδέν σε διακομιστή που βρίσκεται στο διαδίκτυο τουλάχιστον μία μέρα, το jail δεν δουλεύει. Συγκρίνετέ το με την πραγματικότητα:

sudo lastb | wc -l

Χιλιάδες αποτυχημένες προσπάθειες στο lastb απέναντι σε μηδενικά στο Fail2ban σημαίνουν ακριβώς ένα πράγμα: το φίλτρο κοιτάζει σε λάθος μέρος.

Η συνηθέστερη αιτία είναι το Debian 12. Δεν εγκαθιστά πια το rsyslog από προεπιλογή, το αρχείο /var/log/auth.log απλώς δεν υπάρχει και το προεπιλεγμένο jail sshd είναι ρυθμισμένο να διαβάζει αυτό το αρχείο. Δεν υπάρχει μήνυμα σφάλματος γι' αυτό: η υπηρεσία ξεκινά, η κατάσταση τυπώνεται, οι μετρητές μένουν στο μηδέν. Η διόρθωση είναι η μετάβαση στο ημερολόγιο του systemd:

[sshd]
enabled = true
backend = systemd

Η άλλη επιλογή είναι να επαναφέρετε το rsyslog ως πακέτο, αν ένα απλό κειμενικό auth.log έχει σημασία για άλλα εργαλεία. Το Ubuntu 24.04 συμπεριφέρεται με τον ίδιο τρόπο.

Πού μπαίνουν οι ρυθμίσεις σας

Αφήστε το /etc/fail2ban/jail.conf ήσυχο: αντικαθίσταται με την ενημέρωση του πακέτου και κάθε αλλαγή που γίνεται εκεί θα εξαφανιστεί κάποια μέρα αθόρυβα. Οι δικές σας ρυθμίσεις πάνε στο /etc/fail2ban/jail.local — αυτό το αρχείο διαβάζεται τελευταίο και υπερισχύει του κοινού.

[DEFAULT]
ignoreip = 127.0.0.1/8 ::1 203.0.113.25
bantime  = 1h
findtime = 10m
maxretry = 5
backend  = systemd

Το ignoreip με τη δική σας διεύθυνση δεν είναι πολυτέλεια αλλά ασφάλιση: το να κλειδωθείτε απέξω με ένα τυπογραφικό λάθος είναι ευκολότερο απ' ό,τι ακούγεται. Αν δεν έχετε στατική διεύθυνση, κρατήστε δεύτερο τρόπο εισόδου εκτός του SSH — την κονσόλα του παρόχου σας ή VNC.

Το jail που αλλάζει την εικόνα: recidive

Ένα συνηθισμένο jail έχει κοντή μνήμη: πέντε προσπάθειες σε δέκα λεπτά, μία ώρα αποκλεισμού και μετά από μία ώρα όλα ξεκινούν από την αρχή. Ένα bot ζει άνετα με αυτό και θα επιστρέψει αύριο και μεθαύριο. Το recidive κλείνει ακριβώς αυτό το κενό: διαβάζει όχι το ημερολόγιο του συστήματος αλλά του ίδιου του Fail2ban, δηλαδή αποκλείει όποιον έχει ήδη αποκλείσει το Fail2ban.

[recidive]
enabled  = true
bantime  = 1w
findtime = 1d
maxretry = 5

Διαβάστε το ως «αποκλείστηκε πέντε φορές σε μία μέρα, φεύγει για μία εβδομάδα». Το jail χρειάζεται το αρχείο /var/log/fail2ban.log, οπότε αν έχετε μεταφέρει την καταγραφή του Fail2ban στο syslog, το recidive θα χρειαστεί κι αυτό backend = systemd.

Στην πράξη το αποτέλεσμα αυτού του ενός jail είναι συνήθως πιο αισθητό από τη λεπτομερή ρύθμιση όλων των υπολοίπων: οι θαμώνες φεύγουν και στα αρχεία μένει μόνο φρέσκο υπόβαθρο.

Τι άλλο να ενεργοποιήσετε όταν ο διακομιστής φιλοξενεί ιστότοπο

Κατά φθίνουσα χρησιμότητα:

  • nginx-http-auth ή apache-auth — τυφλή δοκιμή κωδικών εναντίον της βασικής πιστοποίησης. Χρειάζεται αν μια περιοχή διαχείρισης ή ένας δοκιμαστικός ιστότοπος βρίσκονται πίσω από κωδικό του διακομιστή ιστού·
  • nginx-botsearch — σάρωση για γνωστές διαδρομές: /wp-login.php, /phpmyadmin, /.env. Αυτό δεν είναι παραβίαση αλλά αναγνώριση, και είναι ό,τι προηγείται όλων των άλλων·
  • nginx-limit-req — δουλεύει μόνο αν έχει οριστεί limit_req_zone στο ίδιο το Nginx· χωρίς αυτό το jail είναι ενεργοποιημένο και άχρηστο·
  • postfix-sasl και dovecot — απαραίτητα αν έχετε δικό σας ταχυδρομείο. Η μαντεψιά κωδικών εναντίον γραμματοκιβωτίων είναι συνεχής και συνήθως δεν την παρακολουθεί κανείς.
[nginx-botsearch]
enabled = true
logpath = /var/log/nginx/access.log

Η φόρμα σύνδεσης του ίδιου του ιστότοπου είναι ξεχωριστή ιστορία. Η εφαρμογή δεν έχει δικό της αρχείο αποτυχημένων συνδέσεων και στο access.log μια αποτυχημένη προσπάθεια μοιάζει με συνηθισμένο POST με 200 ή 302 — μη διακρίσιμη από μια επιτυχημένη με οποιοδήποτε γενικό φίλτρο. Υπάρχουν δύο επιλογές: να κάνετε την εφαρμογή να γράφει τις αποτυχίες στο syslog (τα περισσότερα συστήματα διαχείρισης περιεχομένου έχουν πρόσθετο γι' αυτό) ή να περιορίσετε τον ρυθμό αιτημάτων προς τη σελίδα σύνδεσης. Το δεύτερο είναι περιοριστής, όχι ανιχνευτής, και είναι καλύτερα να το ξέρετε εκ των προτέρων.

Οι αριθμοί

Το bantime = 10m είναι η προεπιλογή που κάνει τον κόσμο να γράφει το Fail2ban στα άχρηστα: δέκα λεπτά αρκούν για να επιστρέψει ένα bot. Μία ώρα για τον πρώτο αποκλεισμό συν recidive για μία εβδομάδα δουλεύει πολύ καλύτερα από μόνιμους αποκλεισμούς, που με τον καιρό μετατρέπονται σε ατέλειωτη λίστα κανόνων.

Το maxretry = 3 για SSH είναι ένας σίγουρος τρόπος να κλειδωθείτε απέξω. Πέντε προσπάθειες σε δέκα λεπτά κόβουν την τυφλή δοκιμή εξίσου καλά.

Η αργή μαντεψιά — μία προσπάθεια κάθε πέντε λεπτά — δεν θα πέσει ποτέ μέσα στο findtime. Αυτό δεν είναι λόγος να τεντώσετε το παράθυρο σε μία μέρα: θα πάρετε ψευδώς θετικά εναντίον των ίδιων σας των συναδέλφων. Απέναντι στην αργή μαντεψιά δουλεύει όχι ένα κατώφλι αλλά η απενεργοποιημένη πιστοποίηση με κωδικό.

Βεβαιωθείτε ότι ο αποκλεισμός φτάνει στα πακέτα

Το Fail2ban απλώς καλεί μια εξωτερική εντολή. Αν το banaction δεν ταιριάζει με ό,τι πραγματικά φιλτράρει την κίνηση, το αρχείο θα γεμίσει με χαρούμενες γραμμές Ban 198.51.100.7 ενώ τα πακέτα θα συνεχίζουν να φτάνουν. Το Debian 12 χρησιμοποιεί nftables από προεπιλογή και με ενεργοποιημένο UFW η σωστή επιλογή είναι banaction = ufw. Για έλεγχο:

sudo nft list ruleset | grep -c f2b
sudo iptables -S | grep f2b

Τουλάχιστον μία από τις δύο πρέπει να δείχνει κανόνες. Και μπορείτε να δοκιμάσετε το ίδιο το φίλτρο χωρίς να περιμένετε επίθεση:

sudo fail2ban-regex systemd-journal /etc/fail2ban/filter.d/sshd.conf

Στο τέλος της εξόδου λέει πόσες γραμμές ταίριαξαν. Το μηδέν σημαίνει ότι το φίλτρο και το αρχείο δεν συναντιούνται και δεν έχει νόημα να ρυθμίσετε τίποτα παραπέρα.

Τι δεν κάνει το Fail2ban

Δεν προστατεύει από κατανεμημένη τυφλή δοκιμή: χίλιες διευθύνσεις με μία προσπάθεια η καθεμία δεν θα φτάσουν ποτέ σε κατώφλι με οποιεσδήποτε ρυθμίσεις. Δεν διορθώνει την αιτία — ένας αποκλεισμένος αποστολέας δεν αναιρεί έναν αδύναμο κωδικό. Και δεν ξέρει τίποτα για φήμη: μια διεύθυνση που πέρασε τη χθεσινή μέρα παραβιάζοντας ξένους διακομιστές είναι καθαρή γι' αυτό μέχρι να ξεκινήσει με τον δικό σας. Εξ ου και ο συνδυασμός που χρησιμοποιείται στην πράξη: κλειδιά αντί για κωδικούς, Fail2ban ως περιοριστής θορύβου και μια κοινή λίστα αποκλεισμού (CrowdSec) ως γνώση της ξένης εμπειρίας.

Ξεχωριστό πρόβλημα είναι ότι όλα αυτά χρειάζονται κάπου κάπου μια ματιά. Κανείς δεν πληκτρολογεί fail2ban-client status ανά jail επί εβδομάδες, και ο αυξανόμενος αριθμός αποκλεισμών γίνεται αντιληπτός αφού κάτι έχει ήδη χαλάσει. Στις σελίδες επίδειξης παρακάτω τα ίδια δεδομένα βρίσκονται σε μία σελίδα: η λίστα των jails, ποιος είναι αποκλεισμένος αυτή τη στιγμή και από πού έρχονται οι προσπάθειες.