Globalny system banowania agresorów na serwerach (opisywany przeze mnie wcześniej) działa świetnie... dopóki nie trafisz na serwery webowe za Cloudflare.
Wtedy pojawia się problem, który kosztował mnie kilkanaście GB RAM-u 🧵 ↓
Ostatnio opisywałem, jak działa u mnie system banowania agresorów na całej flocie serwerów Mikrusa.
Agresor dotyka 'pliku pułapki' i dostaje bana na IP w firewallu na setkach serwerów. Proste, skuteczne, działa wszędzie.
Znaczy... prawie wszędzie ;)
Część moich serwerów to serwery webowe, które przyjmują ruch TYLKO od Cloudflare. Działa na nich serwer webowy Apache2.
Jeśli wytnę agresora na firewallu, to zupełnie nic to nie da.
Dlaczego? Bo mój serwer nie dostaje ruchu z jego IP, tylko z Cloudflare (proxy).
Muszę więc taki bany zakładać na poziomie serwera webowego, a nie firewalla.
To wydawało się dziecinnie proste
Założyłem nowy plik konfiguracyjny z listą banów (IP). Apache go wczytywał i gotowe. Jest jednak pewne "aleee".
Apache na serwerach webowych zaczął niesamowicie puchnąć.
Po miesiącu zjadał nawet kilkanaście GB RAM-u przy małym ruchu.
Dlaczego? Bo za każdym razem, gdy modyfikuję listę banów, muszę wykonać "reload", aby Apache wczytał listę od początku.
To powoduje spore wycieki pamięci i namnażanie się śmieci w przestrzeni adresowej Apache.
Mogłem oczywiście zamiast "reload" zrobić "restart".
Problemu z pamięcią by nie było, ale...
Za każdym razem, gdy jakikolwiek atakujący dostawałby bana, moje strony znikałyby z internetu na około 5 sekund - mało komfortowe.
Biorąc pod uwagę, jak często te bany są rozdawane, drastycznie obniżyłoby to dostępność stron.
To nie wchodziło w grę.
Przerzuciłem się więc na mechanizm mod_rewrite.
Obsługuje on tak zwane 'rewrite-mapy', czyli dynamiczne warunki bazujące na statycznych plikach konfiguracyjnych.
Jeśli coś w nich zmodyfikujemy, to bez restartowania serwera zmiany zaciągane są natychmiast.
Możesz zapytać: To dlaczego nie użyć po prostu .htaccess?
Ano dlatego, że serwisów w ramach jednego serwera jest niesamowicie dużo.
Mój generator musiałby nadpisywać 100+ .htaccess-ów dla różnych domen.
Preferuję mieć jedno źródło prawdy, więc wrzuciłem do Apache plik o nazwie "conf-available/banujemy.conf" o zawartości:
RewriteMap bany "txt:/etc/apache2/bany.txt"
Wspomniany plik TXT wygląda następująco:
1.2.3.4 1
5.5.5.5 1
Czyli adres IP, spacja i jedynka po nim.
Następnie w każdym vhoście mam wpisane:
Include conf-available/banujemy.conf
RewriteEngine On
RewriteCond ${bany:%{REMOTE_ADDR}|0} =1
RewriteRule .* - [G]
Co to robi?
1) Wczytaj plik z definicją blokad
2) Włącz silnik rewrite (będzie potrzebny do obsługi map)
3) Szukaj w bazie danych 'bany' (to ten plik TXT) adresu IP agresora i jeśli on istnieje i ma przypisaną wartość '1' idź do punktu 4
4) Odpowiedz na wszystko "410 Gone"
Dzięki temu rozwiązaniu mogę jednocześnie korzystać z Cloudflare, jak i z mojego systemu banowania adresów IP i to bez przeładowywania Apache za każdym razem.