Fail2Ban jest pewnego rodzaju nakładką na IPtables które to właściwie zabezpieczają serwer, Fail2Ban działa automatycznie, na podstawie reguł które zdefiniujemy dla wybranych usług lub portów. Co ciekawe dzięki temu narzędziu możemy zdać sobie sprawę jak często nasz serwer jest atakowany, co może być lekko denerwujące gdy dostaje się ponad 200 emaili dziennie o nieudanych próbach logowania do serwera przez ssh! Dlatego też zalecam dodatkowe utworzenie reguły iptables która powoduje że można się połączyć z serwerem jedynie z określonych adresów ip, lub ip z określonego zakresu jeżeli logujemy się zdalnie z domu a mamy zmienny adres ip.
Zadaniem programu jest analiza logów systemowych i za pomocą reguł szukanie niewłaściwych zachowań jak nieudane logowanie, a następnie podejmowanie akcji blokowania po określonej liczbie incydentów w określonych odstępach czasy np 3 nieudane logowania w ciągu 10 minut do ssh z tego samego adresu ip. Po identyfikacji potencjalnego boota lub włamywacza trafia on do więzienia czyli „jail”
Instalacja i podstawowa konfiguracja
Instalacja aplikacji w systemach Debian i jego pochodnych jak Mint czy Ubuntu jest prosta, wystarczy skorzystać z polecenia:
Kopiujemy domyślny plik /etc/fail2ban/jail.conf zawierający standardową konfigurację do pliku /etc/fail2ban/jail.local gdyż domyślny plik może zostać nadpisany podczas aktualizacji:
I wszelkie podstawowe modyfikacje przeprowadzamy później w nowoutworzonym pliku:
Podstawowa konfiguracja
Najpierw jeżeli mamy świeżo postawiony serwer zainstalujmy program do wysyłki maili
następnie sprawdź jego poprawne funkcjonowanie:
Poniżej parametry które warto zmienić aby maile przychodziły z powiadomieniami.
# Jeśli posiadasz stały adres IP - możesz go tu wpisać, zamiast aaa.bbb.ccc.ddd
# wpisanie tego adresu spowoduje dodanie ciebie do białej loisty i nie będziesz blokowany możesz też dodać adres podsieci jeżeli twój adres ip zmienia tylko końcówkę
# np 88.66.0.0/16 lub 88.66.55.0/24
ignoreip = 127.0.0.1/8 aaa.bbb.ccc.ddd
# Domyślny czas blokady w sekundach (86400 = 24 godziny):
bantime = 86400
# Domyślna ilość prób logowania zakończonych niepowodzeniem:
maxretry = 3
# Czas do wyzerowania licznika nieudanych prób. Po tym czasie licznik zacznie liczyć od zera ponowne próby logowania:
findtime = 3600
Warto też poddać modyfikacji:
# iptables-multiport, shorewall, etc) It is used to define
# action_* variables. Can be overridden globally or per
# section within jail.local file
#banaction = iptables-multiport
banaction = iptables-allports
#mta = sendmail
mta = mail
action_ = %(banaction)s[name=%(__name__)s, port="%(port)s", protocol="%(protocol)s", chain="%(chain)s"]
# definiujemy blokade i wysyłkę na nasz adres mailowy. W treści zaś będzie wypisane odpytanie z bazy whois
action_mw = %(banaction)s[name=%(__name__)s, port="%(port)s", protocol="%(protocol)s", chain="%(chain)s"]
%(mta)s-whois[name=%(__name__)s, dest="%(destemail)s", protocol="%(protocol)s", chain="%(chain)s"]
%(mta)s-whois-lines[name=%(__name__)s, dest="%(destemail)s", logpath=%(logpath)s, chain="%(chain)s"]
#Wybieramy domyślną czynność kiedy jakiś adres trafi do jail (więzienia). Czyli wysyłka maila w naszym przypadku
action = %(action_mw)s
Konfigurujemy więzienia
Dalej (w tym samym pliku) definiujemy więzienia – część jest już wstępnie zdefiniowana, wystarczy je tylko aktywować i ew zmodyfikować parametry (jeśli zajdzie taka potrzeba).
Sam najczęściej korzystam z więzienia dla szturmujących SSH:
enabled = true
port = 22,ssh,sftp
filter = sshd
logpath = /var/log/auth.log
maxretry = 2
enabled = true
port = 22,ssh,sftp
filter = sshd-ddos
logpath = /var/log/auth.log
maxretry = 3
Oraz w zależnie od serwera www – Apache2:
enabled = true
port = http,https
filter = apache-auth
logpath = /var/log/apache*/*error.log
maxretry = 3
enabled = true
port = http,https
filter = apache-noscript
logpath = /var/log/apache*/*error.log
maxretry = 6
enabled = true
port = http,https
filter = apache-overflows
logpath = /var/log/apache*/*error.log
maxretry = 2
Lub – teraz częściej – Nginx:
enabled = true
filter = nginx-http-auth
port = http,https
logpath = /var/log/nginx/*error.log
enabled = true
port = http,https
filter = nginx-badbots
logpath = /var/log/nginx/*access.log
maxretry = 2
enabled = true
port = http,https
filter = nginx-noproxy
logpath = /var/log/nginx/*access.log
maxretry = 2
Pozostałych domyślnych reguł albo nie używam, albo korzystam z na tyle specyficznych reguł, że nie ma sensu ich tu podawać.
Jeśli modyfikowaliście ścieżkę plików z logami dla danej usługi, i jest ona inna, niz standardowa/domyślna, to pamiętajcie by odpowiednio ustawić parametr „logpath”, w którym znajduje się ścieżka do tych plików (w innym przypadku Fail2Ban nie zadziała dla tej usługi, gdyż nie będzie mógł znaleźć podejrzanych działań w pliku z logiem).
Fail2Bank i Nginx
Jeśli korzystacie z webserwera Nginx (albo dowolnej innej usługi, której nie było w standardzie, i sami ją definiujecie) i dodaliście powyższe reguły (poza „nginx-http-auth”), to musimy jeszcze utworzyć odpowiednie filtry, które będą „tłumaczyły” Fail2Ban jak czytać i czego szukać w danym pliku log.
W tym zadaniu można posiłkować się już zdefiniowanymi filtrami, które można albo wykorzystać bezpośrednio, lub wykorzystać jako wzór. Część przydatnych filtrów znajdziecie również na tej stronie.
Nowe (dodatkowe) filtry
Filtry znajdują się w katalogu:
I tu będziemy tworzyć nowe, ew edytować istniejące.
Nazwa pliku z filtrem (+ rozszerzenie .conf) odpowiada nazwie zdefiniowanej w pliku „jail.local”, a konkretnie linijce „filter” dla danego więzienia/pułapki.
Nie będę też wnikał w szczegóły kolejnych plików z filtrami, tylko przedstawie je w takiej formie, jakiej najczęściej (ale nie zawsze) sam używam – wynika to z tego, że pliki te „chodzą ze mną” między różnymi serwerami od jakiegoś już czasu, czasem wymieniam się nimi (jak i samymi pomysłami na kolejną pułapkę/więzienie) ze znajomymi, i pewnie dojście do sedna, zajęłoby za dużo czasu.
Złe boty „pożyczymy” sobie z pliku przeznaczonego dla Apache:
Próby zrobienia sobie z naszego serwera proxy wytniemy za pomocą filtra który stworzymy:
O treści:
failregex = ^ -.*GET http.*
ignoreregex =
Na koniec musimy jeszcze zrestartować usługę:
Przetestuj działanie
Po konfiguracji i restarcie usługi możecie sprawdzić status usługi, w tym ilość i nazwy więzień/pułapek:
W odpowiedzi otrzymacie np. coś takiego:
|- Number of jail: 5
`- Jail list: nginx-noproxy, nginx-badbots, nginx-http-auth, ssh-ddos, ssh
Możecie też sprawdzić status konkretnego więzienia/pułapki:
I w odpowiedzi dostaniecie np. coś takiego:
|- filter
| |- File list: /var/log/nginx/access.log
| |- Currently failed: 1
| `- Total failed: 65
`- action
|- Currently banned: 1
| `- IP list: aaa.bbb.yyy.zzz
`- Total banned: 6
Możecie też sprawdzić IPtables pod kontem blokad nałożonych przez Fail2Ban za pomocą polecenia:
jeżeli polecenie nie zadziała należy zamienić f2b na fail2ban
I przykładowa odpowiedź:
-N f2b-sshd
-A INPUT -p tcp -j f2b-ssh
-A INPUT -p tcp -j f2b-sshd
-A f2b-ssh -s 186.183.227.104/32 -j REJECT --reject-with icmp-port-unreachable
-A f2b-ssh -s 178.32.19.18/32 -j REJECT --reject-with icmp-port-unreachable
-A f2b-ssh -s 121.201.110.217/32 -j REJECT --reject-with icmp-port-unreachable
-A f2b-ssh -s 201.132.209.2/32 -j REJECT --reject-with icmp-port-unreachable
-A f2b-ssh -s 162.243.226.222/32 -j REJECT --reject-with icmp-port-unreachable
-A f2b-ssh -s 100.40.110.210/32 -j REJECT --reject-with icmp-port-unreachable
-A f2b-ssh -s 183.146.16.23/32 -j REJECT --reject-with icmp-port-unreachable
-A f2b-ssh -s 197.156.93.185/32 -j REJECT --reject-with icmp-port-unreachable
-A f2b-ssh -s 121.184.64.15/32 -j REJECT --reject-with icmp-port-unreachable
-A f2b-ssh -s 159.122.149.247/32 -j REJECT --reject-with icmp-port-unreachable
-A f2b-ssh -s 202.71.176.110/32 -j REJECT --reject-with icmp-port-unreachable
-A f2b-ssh -s 200.24.248.27/32 -j REJECT --reject-with icmp-port-unreachable
-A f2b-ssh -j RETURN
-A f2b-sshd -s 186.178.61.95/32 -j REJECT --reject-with icmp-port-unreachable
-A f2b-sshd -s 61.184.247.3/32 -j REJECT --reject-with icmp-port-unreachable
-A f2b-sshd -s 223.111.139.210/32 -j REJECT --reject-with icmp-port-unreachable
-A f2b-sshd -j RETURN
Można rówież skorzystać zamiennie z polecenia:
W ramach odpowiedzi dostaniemy listę blokad (w tym przypadku dla SSH) z przypisanymi im numerami:
num pkts bytes target prot opt in out source destination
1 0 0 REJECT all -- * * 186.178.x.x 0.0.0.0/0 reject-with icmp-port-unreachable
2 0 0 REJECT all -- * * 186.183.x.x 0.0.0.0/0 reject-with icmp-port-unreachable
3 0 0 REJECT all -- * * 178.32.x.x 0.0.0.0/0 reject-with icmp-port-unreachable
51 3501 407K RETURN all -- * * 0.0.0.0/0 0.0.0.0/0
Dzięki temu możemy szybko dokonać odblokowania wybranej pozycji bez zbędnego komplikowania polecenia:
Gdzie 1 to numer reguły/blokady do skasowania.
Może się zdarzyć, że zamiast „fail2ban-*” będzie „f2b-*”. Wtedy należy lekko zmodyfikować powyższe komendy:
sudo iptables -D f2b-ssh 1
sudo iptables -L f2b-sshd -v -n --line-numbers
sudo iptables -D f2b-sshd 1
Pamiętajcie jeżeli będziecie przeprowadzać testy nie zablokować siebie na zbyt długi czas. Więc albo dodajcie swój adres z którego się logujecie przez ssh do wyjątków albo skrócie czas banowania / osadzania w więzieniu na minutę.
I jeszcze ważna polecenie które może się przydać do odblokowania adresu ip użytkownika który zapomina haseł 😉
Ochrona wordpressa
Dzięki modułowej budowie Fail2Ban możemy dodawać nowe filtry i akcje. Dobrym przykładem jest wtyczka do Wordpresa wp-fail2ban ze strony https://wordpress.org/plugins/wp-fail2ban/. lub na stronie z wtyczkami.
Plik wp-fail2ban.php kopiujemy do katalogu (główny katalog wordpressa)/wp-content/plugins/wp-fail2ban/. Włączamy wtyczkę w kokpicie WordPressa.
Plik wordpress-soft.conf wordpress-hard.conf lub kopiujemy do katalogu filtrów /etc/fail2ban/filter.d/
cp /var/www/html/mojastrona.pl/wp-content/plugins/wp-fail2ban/filters.d/wordpress-soft.conf /etc/fail2ban/filter.d/
Następnie w pliku /etc/fail2ban/jail.local dopisujemy następujące liniki:
enabled = true
filter = wordpress-hard
logpath = /var/log/auth.log
maxretry = 1
port = http,https
[wordpress-soft]
enabled = true
filter = wordpress-soft
logpath = /var/log/auth.log
maxretry = 3
port = http,https
Fail2Ban to nie tylko ochrona przed próbami zgadnięcia hasła, ale również przed zautomatyzowanymi atakami DDoS. Dzięki zablokowaniu podejrzanego ruchu z sieci zaoszczędzamy moc obliczeniową i pamięć, dzięki czemu nasz serwer będzie pracował wydajniej nie tracąc czasu na sprawdzanie czy użytkownik i hasło jest właściwe. Pliki logowania umożliwiają na łatwy sposób wyłowienia zagrożenia, zaś modułowa budowa i wyrażenia regularne w filtrach pozwalają dostosować do zapotrzebowań fail2ban np. pod nowe usługi lub istniejące jak np. sklepy internetowe.