Trwała czarna lista IP z Fail2ban, UFW i Ipset
Wstęp: Poza tymczasową ochroną
W cyfrowym świecie, gdzie ataki na serwery są na porządku dziennym, sama reakcja nie wystarczy. Choć narzędzia takie jak Fail2ban stanowią podstawową linię obrony, ich tymczasowe blokady pozostawiają lukę – uporczywi atakujący, po upływie czasu bana, mogą wrócić i próbować ponownie. Ten artykuł stanowi szczegółowy przewodnik po budowie w pełni zautomatyzowanego, dwuwarstwowego systemu, który zamienia efemeryczne bany w trwałe, globalne blokady. Połączenie Fail2ban, UFW oraz potężnego narzędzia Ipset tworzy mechanizm, który trwale chroni serwer przed znanymi recydywistami.
Warstwa pierwsza: Reakcja z Fail2ban
Na początku każdego ataku stoi Fail2ban. Ten daemon monitoruje pliki logów (np. sshd.log
, apache.log
) w poszukiwaniu wzorców świadczących o próbach włamania – na przykład wielu nieudanych prób logowania. Gdy wykryje taką aktywność, natychmiastowo blokuje adres IP atakującego, dodając go do reguł firewalla na zdefiniowany czas (np. 10 minut, 30 dni). Jest to skuteczna, ale krótkotrwała reakcja.
Warstwa druga: Trwałość z UFW i Ipset
Aby ban stał się trwały, potrzebujemy silniejszej, scentralizowanej metody zarządzania adresami IP. W tym miejscu wkraczają UFW i Ipset.
Czym jest Ipset?Ipset to rozszerzenie do jądra Linuksa, które pozwala na zarządzanie zbiorami (setami) adresów IP, sieci, czy portów. Jest to znacznie bardziej wydajne rozwiązanie niż dodawanie tysięcy pojedynczych reguł do firewalla. Zamiast tego, firewall może odwołać się do całego zestawu za pomocą jednej reguły.
Instalacja i konfiguracja IpsetPierwszym krokiem jest instalacja Ipset w systemie. Używamy do tego standardowych menedżerów pakietów:sudo apt updatesudo apt install ipsetNastępnie tworzymy dwa zestawy: blacklist dla adresów IPv4 i blacklist_v6 dla IPv6.
sudo ipset create blacklist hash:ip hashsize 4096
sudo ipset create blacklist_v6 hash:net family inet6 hashsize 4096
Parametr hashsize określa maksymalną liczbę wpisów, co jest kluczowe dla wydajności.
Integracja Ipset z Firewallem UFWAby UFW zaczął korzystać z naszych zestawów, musimy dodać do jego reguł odpowiednie polecenia. Edytujemy pliki konfiguracyjne UFW, dodając reguły blokujące ruch, który pochodzi z adresów zawartych w naszych zestawach Ipset. Dla IPv4 edytujemy
sudo nano /etc/ufw/before.rules:
Zaraz po:
*filter
:ufw-before-input - [0:0]
dodajemy:
# =======================================================
# Reguły dla trwałej czarnej listy (ipset)
# Blokuj każdy przychodzący ruch od adresów IP z zestawu 'blacklist' (IPv4)
-A ufw-before-input -m set --match-set blacklist src -j DROP
# =======================================================
Dla IPv6 edytujemy
sudo nano /etc/ufw/before6.rules
Zaraz po
*filter
:ufw6-before-input - [0:0]
dodajemy:
# =======================================================
# Reguły dla trwałej czarnej listy (ipset) - IPv6
# Blokuj każdy przychodzący ruch od adresów IP z zestawu 'blacklist_v6'
-A ufw6-before-input -m set --match-set blacklist_v6 src -j DROP
# =======================================================
Po dodaniu reguł, przeładowujemy UFW, aby weszły w życie:
sudo ufw reload
Skrypt do automatycznej aktualizacji czarnej listy
Sednem systemu jest skrypt, który działa jako pomost między Fail2ban a Ipset. Jego zadaniem jest zbieranie zbanowanych adresów, unikalizowanie ich i synchronizowanie z zestawami Ipset.
sudo nano /usr/local/bin/update-blacklist.sh
Poniżej przedstawiono zawartość skryptu. Działa on w kilku krokach:
- Tworzy tymczasową, unikalną listę adresów IP z logów Fail2ban oraz istniejącej czarnej listy.
- Tworzy tymczasowe zestawy Ipset.
- Czyta adresy z unikalnej listy i dodaje je do odpowiednich zestawów tymczasowych (rozróżniając IPv4 i IPv6).
- Atomowo zamienia stare zestawy Ipset na nowe, tymczasowe, minimalizując ryzyko przerw w ochronie.
- Niszczy stare, tymczasowe zestawy.
- Zwraca podsumowanie liczby zablokowanych adresów.
#!/bin/bash
BLACKLIST_FILE="/etc/fail2ban/blacklist.local"
IPSET_NAME_V4="blacklist"
IPSET_NAME_V6="blacklist_v6"
touch "$BLACKLIST_FILE"
(grep 'Ban' /var/log/fail2ban.log | awk '{print $(NF)}' && cat "$BLACKLIST_FILE") | sort -u > "$BLACKLIST_FILE.tmp"
mv "$BLACKLIST_FILE.tmp" "$BLACKLIST_FILE"
sudo ipset create "${IPSET_NAME_V4}_tmp" hash:ip hashsize 4096 --exist
sudo ipset create "${IPSET_NAME_V6}_tmp" hash:net family inet6 hashsize 4096 --exist
while IFS= read -r ip; do
if [[ "$ip" == *":"* ]]; then
sudo ipset add "${IPSET_NAME_V6}_tmp" "$ip"
else
sudo ipset add "${IPSET_NAME_V4}_tmp" "$ip"
fi
done < "$BLACKLIST_FILE"
sudo ipset swap "${IPSET_NAME_V4}_tmp" "$IPSET_NAME_V4"
sudo ipset swap "${IPSET_NAME_V6}_tmp" "$IPSET_NAME_V6"
sudo ipset destroy "${IPSET_NAME_V4}_tmp"
sudo ipset destroy "${IPSET_NAME_V6}_tmp"
COUNT_V4=$(sudo ipset list "$IPSET_NAME_V4" | wc -l)
COUNT_V6=$(sudo ipset list "$IPSET_NAME_V6" | wc -l)
let COUNT_V4=$COUNT_V4-7
let COUNT_V6=$COUNT_V6-7
[ $COUNT_V4 -lt 0 ] && COUNT_V4=0
[ $COUNT_V6 -lt 0 ] && COUNT_V6=0
echo "Czarna lista i ipset zaktualizowane. Zablokowane IPv4: $COUNT_V4, Zablokowane IPv6: $COUNT_V6"
exit 0
Po utworzeniu skryptu, należy nadać mu uprawnienia do wykonania:
sudo chmod +x /usr/local/bin/update-blacklist.sh
Automatyzacja i trwałość po restarcie
Aby skrypt działał bez ingerencji, używamy harmonogramu cron. Otwieramy edytor crontab dla użytkownika root i dodajemy regułę, która uruchomi skrypt co godzinę:
sudo crontab -e
0 * * * * /usr/local/bin/update-blacklist.sh
lub raz dziennie o 6 rano:
0 6 * * * /usr/local/bin/update-blacklist.sh
Ostatni, ale kluczowy krok, to zapewnienie, że zestawy Ipset przetrwają restart. Zestawy te są domyślnie przechowywane w pamięci RAM. Tworzymy więc usługę systemd
, która zapisze ich stan przed zamknięciem serwera i wczyta go ponownie przy starcie.
sudo nano /etc/systemd/system/ipset-persistent.service
[Unit]
Description=Zapisuje i wczytuje zestawy ipset przy starcie/zamknięciu systemu
Before=network-pre.target
ConditionFileNotEmpty=/etc/ipset.rules
[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/bin/bash -c "/sbin/ipset create blacklist hash:ip --exist; /sbin/ipset create blacklist_v6 hash:net family inet6 --exist; /sbin/ipset flush blacklist; /sbin/ipset flush blacklist_v6; /sbin/ipset restore -f <(grep -v ' create' /etc/ipset.rules)"
ExecStop=/sbin/ipset save -f /etc/ipset.rules
[Install]
WantedBy=multi-user.target
Na koniec włączamy i uruchamiamy usługę:
sudo systemctl daemon-reload
sudo systemctl enable --now ipset-persistent.service
Jak to działa w praktyce?
Cały system to zautomatyzowany łańcuch zdarzeń, który działa w tle, chroniąc serwer przed atakami. Oto, jak wygląda przepływ informacji i działań:
- Reakcja na atak (Fail2ban):
- Ktoś próbuje się włamać na serwer (np. wielokrotnie podając błędne hasło przez SSH).
- Fail2ban, monitorując logi systemowe (
/var/log/fail2ban.log
), wykrywa ten wzorzec. - Natychmiast dodaje adres IP atakującego do tymczasowej reguły firewalla, blokując mu dostęp na określony czas.
- Trwałe banowanie (Skrypt i cron):
- Co godzinę (zgodnie z ustawieniem w
cron
), system uruchamia skryptupdate-blacklist.sh
. - Skrypt czyta logi Fail2ban, znajduje wszystkie adresy, które zostały zbanowane (linijki zawierające „Ban”), a następnie porównuje je z istniejącą, lokalną czarną listą (
/etc/fail2ban/blacklist.local
). - Tworzy unikalną listę wszystkich zbanowanych adresów.
- Tworzy tymczasowe zestawy
ipset
(blacklist_tmp
iblacklist_v6_tmp
) i dodaje do nich wszystkie adresy z unikalnej listy. - Wykonuje operację
ipset swap
, która atomowo zamienia stare, aktywne zestawy na nowe, zaktualizowane. - UFW, dzięki zdefiniowanym wcześniej regułom, natychmiast zaczyna blokować nowe adresy, które pojawiły się w zaktualizowanych zestawach
ipset
.
- Co godzinę (zgodnie z ustawieniem w
- Trwałość po restarcie (Usługa systemd):
- Działanie Ipset jest ulotne – zestawy istnieją tylko w pamięci. Usługa
ipset-persistent.service
rozwiązuje ten problem. - Przed wyłączeniem/restartem serwera:
systemd
uruchamia polecenieExecStop=/sbin/ipset save -f /etc/ipset.rules
. Zapisuje ono aktualny stan wszystkich zestawówipset
do pliku na dysku. - Po włączeniu/restarcie serwera:
systemd
uruchamia polecenieExecStart=/sbin/ipset restore...
. Wczytuje ono z pliku/etc/ipset.rules
wszystkie zablokowane adresy i automatycznie odtwarza zestawyipset
w pamięci. - Dzięki temu, nawet jeśli serwer zostanie zrestartowany, czarna lista IP pozostaje nienaruszona, a ochrona jest aktywna od pierwszych chwil po uruchomieniu systemu.
- Działanie Ipset jest ulotne – zestawy istnieją tylko w pamięci. Usługa
Podsumowanie i weryfikacja
Zbudowany system to w pełni zautomatyzowana, wielowarstwowa ochrona. Atakujący są tymczasowo banowani przez Fail2ban, a ich adresy są automatycznie dodawane do trwałej czarnej listy, która jest natychmiastowo blokowana przez UFW i Ipset. Usługa systemd zapewnia, że czarna lista przetrwa restarty serwera, chroniąc przed recydywistami na stałe. Aby zweryfikować działanie, można użyć poniższych komend:
sudo ufw status verbose
sudo ipset list blacklist
orazsudo ipset list blacklist_v6
sudo systemctl status ipset-persistent.service
Jak Stworzyć Niezawodną Białą Listę (Whitelist) Adresów IP w UFW i Ipset
Wprowadzenie: Dlaczego Biała Lista Jest Kluczowa?
Podczas konfigurowania zaawansowanych reguł firewalla, zwłaszcza tych, które automatycznie blokują adresy IP (jak w systemach z Fail2ban), istnieje ryzyko przypadkowego zablokowania samego siebie lub kluczowych usług. Biała lista (whitelist) to mechanizm, który działa jak przepustka VIP dla Twojego firewalla – adresy IP umieszczone na tej liście zawsze będą miały dostęp, niezależnie od innych, bardziej restrykcyjnych reguł blokujących.
Ten poradnik pokaże Ci, jak krok po kroku stworzyć solidną i trwałą białą listę, używając UFW (Uncomplicated Firewall) oraz ipset. Jako przykładu użyjemy adresu IP 111.222.333.444
, który chcemy dodać jako zaufany.
Krok 1: Stworzenie Dedykowanego Zestawu ipset
dla Białej Listy
Pierwszym krokiem jest utworzenie osobnego „kontenera” na nasze zaufane adresy IP. Użycie ipset
jest znacznie wydajniejsze niż dodawanie wielu pojedynczych reguł do iptables
.
Otwórz terminal i wpisz następujące polecenie:
sudo ipset create whitelist hash:ip
Co zrobiliśmy?
ipset create
: Polecenie tworzące nowy zestaw.whitelist
: Nazwa naszego zestawu. Jest krótka i jednoznaczna.hash:ip
: Typ zestawu.hash:ip
jest zoptymalizowany do przechowywania i bardzo szybkiego wyszukiwania pojedynczych adresów IPv4.
Krok 2: Dodanie Zaufanego Adresu IP
Teraz, gdy mamy już gotowy kontener, dodajmy do niego nasz przykładowy, zaufany adres IP.
sudo ipset add whitelist 111.222.333.444
Możesz powtórzyć to polecenie dla każdego adresu, który chcesz dodać do białej listy. Aby sprawdzić zawartość listy, użyj polecenia:
sudo ipset list whitelist
Krok 3: Modyfikacja Firewalla – Nadanie Priorytetu Białej Liście
To jest najważniejszy krok. Musimy zmodyfikować reguły UFW tak, aby połączenia z adresów na białej liście były akceptowane natychmiast, zanim firewall zacznie przetwarzać jakiekolwiek reguły blokujące (w tym te z czarnej listy ipset
czy Fail2ban).
Otwórz plik konfiguracyjny before.rules:Jest to plik, w którym znajdują się reguły przetwarzane przed głównymi regułami UFW.
sudo nano /etc/ufw/before.rules
Dodaj regułę ACCEPT
na samej górze: Przejdź na początek pliku i znajdź sekcję *filter
. Zaraz pod linią
:ufw-before-input - [0:0]
, dodaj nasz nowy fragment. Umieszczenie go na samej górze gwarantuje, że zostanie przetworzony jako pierwszy.
*filter
:ufw-before-input - [0:0]
# =======================================================
# Reguła dla białej listy (ipset) - ZAWSZE MA PIERWSZEŃSTWO
# Akceptuj każdy ruch od adresów IP z zestawu 'whitelist'
-A ufw-before-input -m set --match-set whitelist src -j ACCEPT
# =======================================================
-A ufw-before-input
: Dodajemy regułę do łańcucha ufw-before-input
.
-m set --match-set whitelist src
: Warunek: „jeśli źródłowy (src
) adres IP pasuje do zestawu whitelist
„.
-j ACCEPT
: Akcja: „natychmiast zaakceptuj (ACCEPT
) pakiet i przestań przetwarzać dalsze reguły dla tego pakietu”.
Zapisz plik i przeładuj UFW:
sudo ufw reload
Od tego momentu każde połączenie z adresu 111.222.333.444
będzie natychmiast akceptowane.
Krok 4: Zapewnienie Trwałości Białej Listy
Zestawy ipset
są przechowywane w pamięci i znikają po restarcie serwera. Aby nasza biała lista była trwała, musimy upewnić się, że jest ona automatycznie wczytywana przy każdym starcie systemu. Wykorzystamy do tego naszą wcześniej stworzoną usługę
ipset-persistent.service
.
Zaktualizuj usługę systemd
: Musimy ją „nauczyć” o istnieniu nowego zestawu whitelist
.
sudo nano /etc/systemd/system/ipset-persistent.service
Znajdź linię ExecStart
i dodaj do niej polecenia create
i flush
dla whitelist
. Jeśli masz już inne zestawy, po prostu dodaj whitelist
na początku.
# Przykład zaktualizowanej linii
ExecStart=/bin/bash -c "/sbin/ipset create whitelist hash:ip --exist; /sbin/ipset create blacklist hash:ip --exist; /sbin/ipset create blacklist_v6 hash:net family inet6 --exist; /sbin/ipset create blacklist_nets hash:net --exist; /sbin/ipset flush whitelist; /sbin/ipset flush blacklist; /sbin/ipset flush blacklist_v6; /sbin/ipset flush blacklist_nets; /sbin/ipset restore -f <(grep -v '^create' /etc/ipset.rules)"
Najprościej jest zastąpić całą linię ExecStart
jej kompletną wersją, uwzględniającą wszystkie Twoje zestawy.
Przeładuj konfigurację systemd
:
sudo systemctl daemon-reload
Zapisz aktualny stan wszystkich zestawów do pliku: To polecenie nadpisze stary plik /etc/ipset.rules
nową wersją, która zawiera już informacje o Twojej białej liście.
sudo ipset save > /etc/ipset.rules
Zrestartuj usługę, aby upewnić się, że działa z nową konfiguracją:
sudo systemctl restart ipset-persistent.service
Podsumowanie
Gratulacje! Stworzyłeś solidny i niezawodny mechanizm białej listy. Dzięki niemu możesz bezpiecznie zarządzać swoim serwerem, mając pewność, że zaufane adresy IP, takie jak 111.222.333.444
, nigdy nie zostaną przypadkowo zablokowane. Pamiętaj, aby dodawać do tej listy tylko w pełni zaufane adresy, takie jak Twój domowy lub biurowy adres IP.
Jak efektywnie blokować adresy IP i podsieci na serwerze Linux
Blokowanie pojedynczych adresów IP jest łatwe, ale co, jeśli atakujący używają wielu adresów z tej samej sieci? Ręczne banowanie każdego z nich jest nieefektywne i czasochłonne.
W tym artykule dowiesz się, jak wykorzystać narzędzia ipset
i iptables
, aby skutecznie blokować całe podsieci, automatyzując ten proces i oszczędzając cenny czas.
Dlaczego blokowanie całych podsieci jest lepsze?
Wiele ataków, zwłaszcza tych typu „brute-force”, jest przeprowadzanych z wielu adresów IP należących do tego samego operatora lub z tej samej puli adresów (podsieci). Blokowanie tylko jednego z nich jest jak łatanie małej dziury w dużej zaporze — reszta ruchu wciąż może się przedostać.
Zamiast tego, możesz zablokować całą podsieć, na przykład 45.148.10.0/24. Taki zapis oznacza, że blokujesz aż 256 adresów jednocześnie, co jest znacznie skuteczniejsze.
Skrypt do automatycznego blokowania podsieci
Aby zautomatyzować proces, możesz użyć poniższego skryptu bash. Skrypt ten jest interaktywny — prosi Cię o podanie podsieci do zablokowania, a następnie dodaje ją do listy ipset
oraz zapisuje w pliku, dzięki czemu będzie trwale zablokowana.
Przeanalizujmy skrypt krok po kroku:
#!/bin/bash
# Nazwa listy ipset, do której będą dodawane podsieci
BLACKLIST_NAME="blacklist_nets"
# Plik, do którego będą dopisywane zablokowane podsieci
BLACKLIST_FILE="/etc/fail2ban/blacklistnet.local"
# 1. Tworzy plik z czarną listą, jeśli jeszcze nie istnieje
touch "$BLACKLIST_FILE"
# 2. Sprawdza, czy lista ipset już istnieje. Jeśli nie, tworzy ją.
# Użycie "hash:net" pozwala na przechowywanie podsieci, co jest kluczowe.
ipset list $BLACKLIST_NAME >/dev/null 2>&1
if [ $? -ne 0 ]; then
sudo ipset create $BLACKLIST_NAME hash:net maxelem 65536
fi
# 3. W pętli prosi użytkownika o podanie podsieci do zablokowania.
# Pętla kończy się, gdy użytkownik wpisze "koniec".
while true; do
read -p "Podaj adres podsieci do zablokowania (np. 192.168.1.0/24) lub wpisz 'koniec': " subnet
if [ "$subnet" == "koniec" ]; then
break
elif [[ "$subnet" =~ ^([0-9]{1,3}\.){3}[0-9]{1,3}\/[0-9]{1,2}$ ]]; then
# Sprawdza, czy wprowadzony format jest poprawny
# Sprawdza, czy podsieć nie jest już w pliku, aby uniknąć duplikatów
if ! grep -q "^$subnet$" "$BLACKLIST_FILE"; then
echo "$subnet" | sudo tee -a "$BLACKLIST_FILE" > /dev/null
fi
# Dodaje podsieć do listy ipset
sudo ipset add $BLACKLIST_NAME $subnet
else
echo "Błąd: Nieprawidłowy format. Podaj adres w formacie 'X.X.X.X/Y'."
fi
done
# 4. Dodaje regułę w iptables, która blokuje cały ruch z adresów na liście ipset.
# Upewnia się, że reguła jest dodawana tylko raz.
if ! sudo iptables -C INPUT -m set --match-set $BLACKLIST_NAME src -j DROP >/dev/null 2>&1; then
sudo iptables -A INPUT -m set --match-set $BLACKLIST_NAME src -j DROP
fi
# 5. Zapisuje reguły iptables, aby przetrwały restart serwera.
# Ten fragment sprawdza, z jakiego narzędzia korzysta system
if command -v netfilter-persistent &> /dev/null; then
sudo netfilter-persistent save
elif command -v service &> /dev/null && service iptables status >/dev/null 2>&1; then
sudo service iptables save
fi
echo "Skrypt zakończył działanie. Lista '$BLACKLIST_NAME' została zaktualizowana, a reguły iptables są aktywne."
Jak używać skryptu
- Zapisz skrypt: Zapisz powyższy kod w pliku, np.
block_nets.sh
- Nadaj uprawnienia: Upewnij się, że plik ma uprawnienia do wykonania:
chmod +x block_nets.sh
- Uruchom skrypt: Wykonaj skrypt z uprawnieniami roota:
sudo ./block_nets.sh
- Podawaj podsieci: Skrypt poprosi Cię o podanie adresów podsieci. Po prostu wpisuj je w formacie
X.X.X.X/Y
i zatwierdzaj Enterem. Po zakończeniu wpiszkoniec
.
Zapewnienie trwałości po restarcie serwera
Zestawy ipset
są domyślnie przechowywane w pamięci RAM i znikają po ponownym uruchomieniu serwera. Aby zablokowane adresy pozostały aktywne, musisz użyć usługi systemd
, która wczyta je przy starcie systemu.
Jeśli masz już taką usługę (np. ipset-persistent.service
), musisz ją zaktualizować, aby uwzględniała nową listę blacklist_nets
.
Edytuj plik usługi: Otwórz plik konfiguracyjny swojej usługi:
sudo nano /etc/systemd/system/ipset-persistent.service
Zaktualizuj linię ExecStart
: Znajdź linię ExecStart
i dodaj do niej polecenia create
i flush
dla zestawu blacklist_nets
.Przykładowa, zaktualizowana linia ExecStart
powinna wyglądać następująco:
ExecStart=/bin/bash -c "/sbin/ipset create whitelist hash:ip --exist; /sbin/ipset create blacklist hash:ip --exist; /sbin/ipset create blacklist_v6 hash:net family inet6 --exist; /sbin/ipset create blacklist_nets hash:net --exist; /sbin/ipset flush whitelist; /sbin/ipset flush blacklist; /sbin/ipset flush blacklist_v6; /sbin/ipset flush blacklist_nets; /sbin/ipset restore -f <(grep -v ' create' /etc/ipset.rules)"
Przeładuj konfigurację systemd
:
sudo systemctl daemon-reload
Zapisz aktualny stan wszystkich zestawów do pliku: To polecenie nadpisze stary plik /etc/ipset.rules
nową wersją, która zawiera już informacje o wszystkich Twoich listach, w tym blacklist_nets
.
sudo ipset save > /etc/ipset.rules
Zrestartuj usługę:
sudo systemctl restart ipset-persistent.service
Dzięki tej metodzie możesz w prosty i wydajny sposób zarządzać bezpieczeństwem swojego serwera, skutecznie blokując całe podsieci, które wykazują podejrzaną aktywność, i mieć pewność, że te reguły pozostaną aktywne po każdym restarcie.
Dodaj komentarz