Prosty sposób na geoblokadę krajów używając ufw

Tagi: #<Tag:0x00007f2addb16de0> #<Tag:0x00007f2addb16cf0>

Hej! :sunglasses:

:thinking: Kilka słów wstępu…
W tym poradniku pokażę Wam chyba najprostszy sposób na zablokowanie dostępu do naszego serwera danym krajom. Opisane jest zarówno jak zastosować blokadę dla danego portu jak i całego ruchu przychodzącego. Przydaje się to na przykład przy blokowaniu botów na serwerach Minecraft, które używają najczęściej zagranicznych adresów (w szczególności z takich krajów jak Chiny, Tajwan czy Rosja - blokując jedynie kilka tego typu krajów już można wyciąć sporą część ruchu). Takie rozwiązanie będzie też znacznie wydajniejsze niż blokada po stronie pluginów, kiedy ruch już dojdzie do serwera i filtrujemy go na poziomie silnika.

:raised_hand_with_fingers_splayed: Metody można użyć na wszystkich serwerach VPS dostępnych w ofercie LVLUP. Użyj kodu rabatowego CRAFTCODE.PL w trakcie składania zamówienia i otrzymaj 10% zniżki. :heart:

:warning: Zastrzegam, że opisany sposób nie jest ani metodą najlepszą ani najszybszą i jestem tego świadomy. Są alternatywne sposoby opisane na tym forum jak skrypt od @SystemZ opisany w poradniku przez @Lumpiasty - dostępny tu. Jest również dostępna jego modyfikacja stworzona przez @Fallen dostępna tutaj. Rozwiązanie opisane przeze mnie ma jednak to do siebie, że jest bardzo proste, działa na najnowszych systemach z rodziny Ubuntu i wymaga jedynie preinstalowanego w nich pakietu ufw, czyli Uncomplicated Firewall. Są lepsze rozwiązania np. używając pakietu ipset, ale po części poradniki do nich mogą być już nieaktualne. Opisana tu metoda sprawdzi się dla początkujących, jest jeszcze jeden jej duży plus o czym wspomniałem na końcu poradnika. :slight_smile:


:facepunch: Do rzeczy…

  1. Na początek sprawdzamy czy mamy zainstalowany pakiet ufw. Jeśli korzystasz z systemu Ubuntu najpewniej tak, ale możesz musieć go jeszcze włączyć komendą ufw enable. Pamiętaj, aby dodać do reguł akceptowanie połączeń do SSH, w innym przypadku nie będziesz mógł się zalogować do konsoli i istniejące połączenie może zostać zerwane! Wykonaj komendę ufw allow ssh lub jeśli korzystasz z usługi SSH na zmienionym porcie podmieniając nazwę na odpowiedni port i protokół TCP np. ufw allow 1337/tcp. Na innych dystrybucjach np. Debian może go w ogóle nie być. Wtedy instalujemy go komendę apt install ufw i również nie zapominamy o początkowym uaktywnieniu.

  2. Następnie wchodzimy na stronę https://www.ip2location.com/free/visitor-blocker i wybieramy z listy kraj, który chcemy zablokować rozwijając pole wyboru pod nazwą Country. W polu Output Format, czyli format naszego pliku z adresami, który uzyskamy wybieramy koniecznie CIDR. Pole IP Version pozostawiamy w domyślnej formie, czyli IPv4.

:information_source: Niezarejestrowany użytkownik może jednocześnie w jednym pliku pobrać listę dla tylko jednego kraju. Jeśli chcesz od razu uzyskać ich więcej, załóż darmowe konto. Zastanowiłbym się jednak nad blokowaniem np. wszystkich krajów poza Polską, bo trzymanie kilkuset tysięcy podobnych reguł może nam narobić niezłego bałaganu, będzie trudne do zeskalowania.

  1. Jeśli pobierzemy plik dla Chin możemy go nazwać np. China.txt i umieścić w głównym folderze na naszej maszynie. Następnie tworzymy nowy plik w tej samej lokalizacji z rozszerzeniem .sh (czyli skrypt powłoki BASH) np. Block_China.sh. Z pliku China.txt możemy usunąć początkowe informacje zanegowane znakiem #. Mój przykładowy plik wygląda tak:
1.0.1.0/24
1.0.2.0/23
1.0.8.0/21
1.0.32.0/19
1.1.0.0/24
1.1.2.0/23
1.1.4.0/22
1.1.8.0/21
1.1.16.0/20
1.1.32.0/19
1.2.0.0/23

i jeszcze prawie 7000 innych adresów… :wink:

  1. Nadajemy uprawnienia do wykonania pliku Block_China.sh komendą:
    chmod +x Block_China.sh
    Oczywiście przy innej nazwie pliku odpowiednio modyfikujemy ją w komendzie.

  2. W utworzonym wcześniej pliku Block_China.sh umieszczamy taki kod:
    while read line; do sudo ufw deny from $line; done < China.txt
    Gdzie China.txt to oczywiście nazwa naszego pliku, z którego będzie pobierało adresy do blokowania. Ta metoda zablokuje nam połączenia przychodzące na wszystkich portach z danych adresów. Jeśli chcemy zablokować np. tylko na porcie 25565 i protokole TCP (na którym najczęściej jest uruchamiany serwer Minecraft i z którego ta gra zawsze korzysta), możemy to zrobić modyfikując komendę w ten sposób:
    while read line; do sudo ufw deny proto tcp from $line to any port 25565; done < China.txt

:speech_balloon: Cały proces w zależności od ilości adresów może chwilę potrwać i w trakcie trwania będą wypluwane komunikaty o dodaniu nowej reguły. Jeśli chcemy sprawdzić, czy wszystko się dodało możemy użyć komendy ufw status numbered.
Jest też sposób na dodanie adresów z kilku osobnych plików do jednego komendą:
cat *.txt >> All_Countries.txt

:star_struck: Gotowe! Opisany sposób ma też jedną zasadniczą zaletę, mianowicie baza adresów z danych krajów jest łatwa do pobrania i dostępna praktycznie bez większych ograniczeń, stosujemy też tu dodanie ich lokalnie, więc nie ma limitowania ilości zapytań tak jak w przypadku innych rozwiązań, które stosują zewnętrzne serwisy. Minus jest taki, że baza czasem może być nieaktualna. Dlatego polecam regularnie, co miesiąc aktualizować listę adresów i wgrywać je na nowo. Jeszcze raz zastrzegę, że to jest metoda dla początkujących, bardzo prosta, kiedy szybko, sytuacyjnie chcemy wyciąć np. ruch z jednego konkretnego kraju w czasie ataku.

:no_entry_sign: No właśnie, a jak usunąć dodane reguły? Zachowujemy ten sam plik, z którego wgrywaliśmy adresy, jedynie w skrypcie podmieniamy komendę na taką, jeśli zablokowaliśmy wszystkie połączenia z danych adresów z listy:
while read line; do sudo ufw delete deny from $line; done < China.txt


Data ostatniej aktualizacji: 18.05.2020 r.

2lajki

Gratulacje, właśnie spowodowałeś, że serwer podczas ataku zużyje wszystkie zasoby na przepuszczanie każdego pakietu przez te tysiące reguł, one-by-one. Nie bez powodu używa się ipset.

Nadmieniłem w temacie, że to nie jest sposób idealny. Przedstawiłem go jedynie jako alternatywę i rozwiązanie np. tymczasowe. Wspomniałem o tym w temacie kilkukrotnie, podlinkowałem nawet do skryptów używających lepszego rozwiązania. Temat może sobie wisieć lub jeśli uważasz to za na tyle szkodliwe i błędne rozwiązanie, to do modyfikacji lub usunięcia.

Jeśli implementacja ufw powoduje, że jest to traktowane jako oddzielne reguły, to nie nadaje się to nawet na tymczasowe rozwiązanie, bo to może tylko pogorszyć stan faktycznie atakowanego serwera. To pozory ochrony.

Sprawdziłem. Dokładnie tak się dzieje:

-A ufw-user-input -s 2.2.2.1/32 -j DROP
-A ufw-user-input -s 2.2.2.2/32 -j DROP
# ...

Podsumowując: równie dobrym rozwiązaniem (a może nawet lepszym) jest wyłączenie serwera :joy:

2lajki

czy wykonanie tej komendy bez uprzedniego dodania portu ssh nie odetnie przypadkiem zdalnego dostępu do serwera? :stuck_out_tongue:

2lajki

Słuszna i ważna uwaga. Dodałem już informację o tym do poradnika. W momencie wykonywania polecenia włączającego zaporę również zresztą jest o tym ostrzeżenie w języku angielskim, ale rozumiem, że można je przeoczyć bądź nie zrozumieć. Dzięki. :slightly_smiling_face:

1lajk