Kompleksowy poradnik dotyczący bezpieczeństwa serwerów Minecraft

Tagi: #<Tag:0x00007f13927c5e78> #<Tag:0x00007f13927c5db0> #<Tag:0x00007f13927c5ce8>

:lock: Kompleksowy poradnik dotyczący bezpieczeństwa serwerów Minecraft

1. Wprowadzenie
Zauważyłem, że na forach cyklicznie przejawiają się podobne tematy dotyczące bezpieczeństwa serwerów Minecraft. Najczęściej zadawane pytania dotyczą sposobów zabezpieczenia przed atakami botów, atakami DoS/DDoS bądź atakami aplikacyjnymi (tzw. crasherami). Aby może trochę ograniczyć ilość tych pytań, postanowiłem, że napiszę taki poradnik, który z czasem być może będzie aktualizowany (data ostatniej zmiany na dole tematu).
Wszystko, co tu napisałem opieram na swojej wiedzy, prawie dziesięcioletnim doświadczeniu w prowadzeniu dużych serwerów (największe projekty przekraczały liczbę 500 graczy). Jednocześnie zastrzegam, że sytuacja zmienia się dynamicznie, są znajdowane nowe sposoby, luki itp.

2. Typy ataków
Sposobów na czasowe niepożądane zatrzymanie działania serwera lub wygenerowanie opóźnień czy innych niedogodności w trakcie rozgrywki jest wiele. Najpopularniejsze z nich to:

  • ataki DoS/DDoS: niegdyś chyba najpopularniejszy typ ataków, w dużym uproszczeniu polega na wysłaniu dużej ilości zapytań do serwera, na które ten nie może odpowiedzieć co prowadzi do przeciążenia łącza i finalnie do znacznych lagów lub nawet crasha serwera. DoS od DDoS różni się tym, że atak DoS jest przeprowadzany z jednego komputera, natomiast DDoS z wielu najczęściej w tzw. sieci botnet (tzw. komputerów zombie). Ten drugi jest zdecydowanie popularniejszy ze względu na większą skuteczność. Do przeprowadzania ataków często są stosowane tzw. bootery/stressery. Więcej przeczytasz tutaj.

  • ataki botów: bardzo popularny problem na wielu serwerach. Atak polega na uruchomieniu specjalnego programu, który najczęściej z różnych adresów IP (tzw. proxy) wpuszcza nawet do kilkuset graczy na sekundę na serwer, co prowadzi do lagów, spamu chatu itp.

  • ataki aplikacyjne: ostatnio bardzo popularny typ ataków. Metod jest mnóstwo, są gotowe skrypty (tzw. crashery). W szczególności na starszych, niewspierany wersjach gry (np. 1.8) silnik ma wiele luk przez co wywołując odpowiednie komendy bądź działania na serwerze możemy zakłócić jego stabilność.

Pewnie można byłoby jeszcze wyróżnić tu więcej kategorii, ale myślę, że lepiej przejść do tej najważniejszej części, czyli jak się przed większością z nich zabezpieczyć, reszta wyjdzie w praniu. :slight_smile:

3. Zabezpieczenie przed włamaniami na serwer spięte z BungeeCordem
Prowadząc sieć serwerów każdy tryb działa osobno (dotyczy się to również serwerów pojedynczych, ale podzielonych na osobne instancje, czyli tzw. sektory). Opiszmy to na przykładzie, będzie prościej.

  • Proxy BungeeCord jest hostowane na porcie 25565,

  • Serwer autoryzacyjny z wyborem trybu i pluginem do rejestracji kont jest hostowany na porcie 25566,

  • Serwer Survival jest hostowany na porcie 25567.
    I teraz musimy zrobić tak, aby gracz mógł połączyć się z każdym serwerem, ale jedynie przez proxy, czyli aby porty 25566 i 25567 były dostępne tylko dla Bungee, a gracz nie mógł się bezpośrednio z nimi połączyć przez listę serwerów. Dlaczego? Bo może wtedy np. wejść bezpośrednio na serwer Survival z pominięciem logowania.
    :warning: Uwaga! Pluginy typu IPWhitelist czy OnlyProxyJoin nie dają pełnej ochrony i nie są zalecane. To bardzo częsty powód włamań na serwerach.
    Jeśli mamy dostęp do konsoli SSH, możemy szybko i bezpiecznie zablokować dostęp do serwerów używając do tego celu IPTables lub prostszego i aktualnie nawet bardziej polecanego ufw.
    Aby zablokować bezpośredni dostęp do serwera na danym porcie, użyj komendy:
    iptables -I INPUT ! -s $BUNGEE_IP -p tcp --dport $SERVER_PORT -j DROP
    :information_source: $BUNGEE_IP to adres Twojego proxy BungeeCord a $SERVER_PORT to port serwera do którego bezpośrednie połączenie chcesz zablokować.
    Jeśli chcesz zablokować zakres portów, jest taka sama zasada, tylko nieco zmieniona regułka:
    iptables -I INPUT ! -s $BUNGEE_IP -p tcp --dport $START_PORT:$END_PORT -j DROP
    :information_source: Zasada z adresem jest taka sama, natomiast $START_PORT zastępujesz początkowym portem, natomiast $END_PORT końcowym, które chcesz zablokować.

:thinking: A co jeśli używasz ufw? Wtedy wystarczy jedna komenda do odblokowania jedynie portu 25565 z danego adresu, bo ten firewall domyślnie blokuje wszystkie połączenia przychodzące, chyba, że reguły stanowią inaczej. W tym przypadku jeśli nasze proxy jest hostowane na tej samej maszynie i ma port 25565 (czyli domyślny), używamy komendy:
ufw allow from localhost to any port 25565 proto tcp

:warning: Domyślnie reguły IPTables są usuwane po restarcie serwera. Na systemach Ubuntu/Debian musisz po dodaniu ich doinstalować pakiet iptables-persistent i przejść przez krótki instalator zaznaczając jedynie, aby zapisać dodane reguły IPv4 i IPv6. Robisz to komendą:
apt-get install iptables-persistent

:information_source: Więcej o zabezpieczeniu BungeeCorda dowiesz się na tej stronie.
A co jeśli nie masz fizycznego dostępu do serwera SSH? Wtedy masz problem. Część hostingów oferuje już firewall w panelu, wtedy wystarczy dodać do reguł (tzw. białej listy) jedynie adres proxy. Ja nie korzystam i nie polecam też większości hostingów Minecrafta ze względu na ich kiepską jakość, więc dokładnie całego procesu nie opiszę. Szukaj informacji w stronach informacyjnych konkretnego hostingu bądź napisz ticketa, aby pomogli. Lub kup VPS’a tutaj. :wink:

4. Zabezpieczenie serwera VPS/dedykowanego
No właśnie, skoro mowa o VPS. Pamiętajmy, że to na nim stoi nasz serwer, znajdują się wrażliwe pliki, więc najpierw to jego należy zabezpieczyć. Jakie są podstawowe czynności, które powinniśmy wykonać po świeżej instalacji systemu?

  • zmiana hasła na losowo wygenerowane (np. przez stronę https://www.random.org/passwords/), które ma minimum 24 znaki i nie jest używane nigdzie indziej. Aby zmienić hasło na serwerze użyj komendy passwd.

  • zmiana portu SSH z domyślnego 22 na jakikolwiek inny. Jak to zrobić? Poradnik autorstwa @Fallen tutaj.

  • Instalacja pakietu fail2ban, dzięki któremu przy zbyt wielu próbach błędnego logowania do SSH czasowo dostęp zostanie zablokowany. Instalujemy komendą apt install fail2ban i nie wymaga większej konfiguracji.

  • Zabezpieczenie bazy danych MySQL/MariaDB. To tej bazy danych używamy najczęściej używamy do pluginów. Po instalacji wykonujemy komendę sudo mysql_secure_installation, ustawiamy tam trudne, losowo wygenerowane hasło (według takiej samej zasady jak do konta SSH, ale inne!), najlepiej blokujemy dostęp spoza localhosta. Podstawowa znajomość języka angielskiego wystarczy do szybkiego przejścia konfiguratora. :slight_smile:

  • Zabezpieczenie bazy danych Redis. Rzadziej używana baza danych, ale bardzo wydajna i przydatna do zapisu danych, które muszą być szybko synchronizowane (np. przy sektorach czy systemu RedisBungee). W pliku konfiguracyjnym Redisa (najczęściej znajdujący się w /etc/redis/redis.conf znajdujemy linijkę requirepass i ustawiamy trudne hasło oraz odhaszowujemy linijkę bind 127.0.0.1 (jeśli jest przed nią znak #).

  • Dopuszczenie logowania do SSH tylko z danego adresu IP. To metoda, która będzie dobra tylko w momencie gdy mamy statyczny adres IP, logujemy się tylko z jednego komputera i mamy jako tako pewność, że ten adres nie ulegnie zmianie. W przeciwnym razie bezpowrotnie utracimy dostęp do danych. Aby to zrobić, możemy użyć znanego nam już pakietu ufw, wykonujemy komendę:
    sudo ufw allow from 203.0.113.4 to any port 22
    :information_source: Jeśli SSH mamy na porcie 22, jeśli na innym, to oczywiście odpowiednio modyfikujemy powyższą komendę oraz wklejamy swój adres.

Pamiętamy również o regularnym aktualizowaniu systemu komendami apt update oraz apt upgrade. Starajmy się nie używać konta root. Nie podajemy nikomu hasła.
To takie absolutne podstawy, w innych poradnikach na forum znajdziecie jeszcze kilka sposobów na zabezpieczenie serwera VPS. :slight_smile:

5. Zabezpieczenie przed atakami DoS/DDoS
Tutaj sprawa ma się tak, że w zasadzie najlepszą ochroną jest wykupienie serwera, który takową ochronę oferuję. Niestety żadne reguły działające po stronie serwera nie dadzą nam skutecznej ochrony z bardzo prostego powodu. Ruch filtrowany będzie już na poziomie powłoki systemu, a więc zapytania będą do niego dochodziły i drenowały zasoby. W tym momencie jedyną i praktycznie bezkonkurencyjną usługę Anty-DDoS oferuje OVH w swoich ofertach GAME. Mitygacja ataków jest szybka, reguły są odpowiednio dostosowane. VPS’y dostępne w hostingu, na którego forum się znajdujemy również taką ochronę posiadają, a w panelu jest możliwość włączenia dodatkowego filtrowania UDP i zmiana reguł.

Przy niektórych typach ataków (np. SYN flood) pomocne mogą być takie reguły IPTables:
iptables -N SYN_FLOOD
iptables -A INPUT -p tcp --syn -j SYN_FLOOD
iptables -A SYN_FLOOD -m limit --limit 1/s --limit-burst 3 -j RETURN
iptables -A SYN_FLOOD -j DROP
iptables -A INPUT -p tcp --tcp-flags SYN,ACK SYN,ACK -m state --state NEW -j DROP
iptables -A INPUT -p tcp --tcp-flags ALL NONE -j DROP
iptables -A INPUT -p tcp --tcp-flags SYN,FIN SYN,FIN -j DROP
iptables -A INPUT -p tcp --tcp-flags SYN,RST SYN,RST -j DROP
iptables -A INPUT -p tcp --tcp-flags ALL SYN,RST,ACK,FIN,URG -j DROP
iptables -A INPUT -p tcp --tcp-flags FIN,RST FIN,RST -j DROP
iptables -A INPUT -p tcp --tcp-flags ACK,FIN FIN -j DROP
iptables -A INPUT -p tcp --tcp-flags ACK,PSH PSH -j DROP
iptables -A INPUT -p tcp --tcp-flags ACK,URG URG -j DROP
iptables -A INPUT -p tcp --tcp-flags ALL FIN,PSH,URG -j DROP
iptables -A INPUT -p tcp --tcp-flags ALL NONE -j DROP
iptables -A INPUT -p tcp --tcp-flags ALL ALL -j DROP
iptables -A INPUT -m conntrack --ctstate INVALID -j DROP

Powyższe reguły mogą jedynie pomóc, ale pamiętajmy, że to, co dzieje się jeszcze przed naszym serwerem jest najistotniejsze, czyli infrastruktura filtrująca samego dostawcy, przepustowość łącza oraz to, ile ataków już przyjęliśmy (bo firewall w OVH można powiedzieć uczy się z każdym atakiem i lepiej filtruje). Więcej o ochronie Anty-DDoS Game przeczytasz tu. O innych nie wspominam, bo można powiedzieć, że nie umywają się do tego, co oferuje OVH. Dowodem na to jest chociażby to, że w zasadzie każdy duży serwer w Polsce aktualnie tam jest hostowany.

6. Crashery BungeeCord i Spigota
Po pierwsze i najważniejsze, zawsze używaj aktualnego softu. Stare wersje (np. 1.7, 1.8) są już niewspierane, więc autorzy Spigota nie odpowiadają za błędy, których wówczas było sporo i jeśli chcesz ich używać, tylko po Twojej stronie spoczywa odpowiedzialność za napisanie łatek.

Aby uchronić się przed różnymi crasherami na BungeeCorda (poprzez np. spamowanie pakietami netty) możesz użyć forka BungeeCorda o nazwie FlameCord, który jest dostępny pod tym linkiem. Niestety, ale domyślne Bungee niewiele robi w celu weryfikacji pakietów. Ten fork nie jest idealny, ale z wszystkich dostępnych za darmo jest najlepszy. Z płatnych jest np. Aegis, który jest na bieżąco wspierany i poprawiany.

Od tego samego autora jest również plugin ExploitFixer, który też nie jest idealny, ale pomaga przy najbardziej prymitywnych metodach ataków na Spigota. Jest dostępny tutaj.

Co jeszcze z takich ogólnych porad? Nie używajcie pluginów typu ServerListPlus, też można tym nabroić wysyłając odpowiednie pakiety.

7. Zabezpieczenie przed botami
Zablokuj połączenia zagraniczne (to ostatnio jest trochę utrudnione ze względu na trudniej dostępne bazy krajów). Ustaw limity połączeń z jednego adresu. Użyj kilku osobnych serwerów do autoryzacji kont, które nie mają premium, żeby rozłożyć ruch i nie wpłynąć na stabilność głównych serwerów. Dodaj plugin, który wymaga spingowania listy serwerów, aby wejść i wyrzuć gracza przy pierwszym wejściu na serwer. Co do wszelkich pluginów typu AntiBot, to mam ambiwalentne podejście, bo często mało co blokują, a lagują albo utrudniają wejście na serwer normalnym graczom. Tu jeden z lepszych tego typu darmowych pluginów: https://www.spigotmc.org/resources/2ls-antibot-the-ultimate-antibot-plugin.62847/

8. CloudFlare, zabezpieczenie strony WWW
Nieodłączną częścią wielu serwerów jest strona WWW. Warto korzystać z CloudFlare, czyli dodatkowej bariery obronnej, która ukrywa realny adres naszego serwera przy pingowaniu. Poza tym umożliwia też włączenie chociażby certyfikatu SSL dla strony, jest analityka itd. Dodajemy rekord typu A oraz SRV dla serwera Minecraft. Więcej o tym tutaj.

9. Poza tym…
Nie używamy pluginów do permisji działających po stronie BungeeCorda. Uważamy na dodawanie uprawnień użytkownikom w Bungee. Nie używamy po stronie proxy ViaVersion, tylko Travertine/Waterfall lub najlepiej wyżej wymionego FlameCord, aby obsługiwać wiele protokołów połączenia. Nie trzymamy żadnych danych wrażliwych danych w plain text w naszych pluginach, tylko szyfrujemy (i to sensowniejszym szyfrem niż MD5 chociażby).

To tyle. :slight_smile: Jeśli macie jakieś propozycje, co można dodać, co zmienić, to śmiało, chciałbym, żeby każdy coś dorzucił ze swojej wiedzy. Jeszcze kilka punktów może będzie dopisane jak będzie mi się chciało. Nie pisałem o takich podstawach jak używaj pluginu do autoryzacji kont, bo wydaje mi się to oczywiste.
Żródła podane w każdym konkretnym podpunkcie + wiedza własna.
Pamiętajcie, że najpierw zabezpieczamy, a nie jak już jesteśmy atakowani, bo wtedy może być za późno, frustracja graczy jest duża, a my ryzykujemy włamaniami, wyciekami plików itp.
Warty uwagi poradnik na GitHubie w języku angielskim: https://github.com/sammwyy/advanced-minecraft-server-security-guide/
Data ostatniej aktualizacji poradnika: 11.03.2019 r. 22:54

Pozdro! :pray:

9lajków

Dopisałbym w przypadku OVH jeszcze coś o ich firewall’u który możemy dodatkowo skonfigurować (dla VPS/Dedyków zakupionych u nich). Chyba w planach jest też możliwość konfiguracji firewalla OVH dla VPS’ów, ale nie wiem czy to pewniak.

Większość tego punktu można zastąpić logowaniem kluczem

3lajki

Czemu? Bind na tylko localhost to jakiś problem? Ok, już widzę o co chodziło.

Funkcje skrótu (md5, sha256) to nie jest szyfrowanie.

przecież jemu chodzi właśnie o odkomentowanie linijki bindującej na localhost. Wydaje mi się, że redis binduje się domyślnie na localhosta, ale lepiej mieć pewność niż jej nie mieć :cowboy_hat_face:

Faktycznie. Przez to, że w domyślnej konfiguracji redisa jest już bind 127.0.0.1, zrozumiałem to jako sugestie zakomentowania dyrektywy.

# By default, if no "bind" configuration directive is specified, Redis listens
# for connections from all the network interfaces available on the server.
# It is possible to listen to just one or multiple selected interfaces using
# the "bind" configuration directive, followed by one or more IP addresses.
#
# Examples:
#
# bind 192.168.1.100 10.0.0.1
# bind 127.0.0.1 ::1
#
# ~~~ WARNING ~~~ If the computer running Redis is directly exposed to the
# internet, binding to all the interfaces is dangerous and will expose the
# instance to everybody on the internet. So by default we uncomment the
# following bind directive, that will force Redis to listen only into
# the IPv4 loopback interface address (this means Redis will be able to
# accept connections only from clients running into the same computer it
# is running).
#
# IF YOU ARE SURE YOU WANT YOUR INSTANCE TO LISTEN TO ALL THE INTERFACES
# JUST COMMENT THE FOLLOWING LINE.
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
bind 127.0.0.1