Monitoring serwera Minecraft: jak śledzić ataki w czasie rzeczywistym

Monitoring serwera Minecraft: jak śledzić ataki w czasie rzeczywistym

Twój serwer Minecraft działa świetnie. Gracze budują, areny PvP hałasują, wszystko stabilne. A potem w jednej chwili wszystko pada. Gracze narzekają na lagi, konsola zasypana błędami, TPS spada do zera. Co się stało? Bez monitoringu nie dowiesz się, póki nie będzie za późno.

Monitoring to nie luksus dla dużych projektów. To podstawowa konieczność dla każdego serwera, który przyjmuje graczy z internetu. W tym artykule rozłożymy wszystko: od prostych komend w terminalu do pełnego stacku z Prometheus i Grafaną, alertami na Discordzie i automatycznymi skryptami reagowania.

Po co w ogóle monitorować

Prosta odpowiedź: wczesne wykrycie = szybka reakcja. Atak DDoS, który zauważyłeś po 30 sekundach, to jedno. Atak, o którym dowiedziałeś się po 15 minutach ze skarg na Discordzie, to kompletnie co innego.

Bez monitoringu jesteś ślepy. Nie wiesz, czy obciążenie serwera jest normalne czy anomalne. Nie możesz odróżnić laga od ataku. Nie możesz udowodnić hosterowi, że problem jest po ich stronie.

Monitoring daje ci trzy rzeczy:

  1. Widoczność - rozumiesz, co dzieje się na serwerze właśnie teraz
  2. Historię - możesz spojrzeć, co było wczoraj, w zeszłym tygodniu, miesiąc temu
  3. Automatyzację - system sam reaguje na anomalie, podczas gdy śpisz

Kluczowe metryki: co śledzić

Nie wszystkie metryki są równie ważne. Oto te, na które trzeba patrzeć w pierwszej kolejności.

Metryki sieciowe

Connections per second (CPS) - liczba nowych połączeń TCP na sekundę. Normalna wartość dla średniego serwera: 1-10 na sekundę. Jeśli widzisz 100+, coś jest nie tak. 1000+ to prawie na pewno atak.

Bandwidth (Mbps) - zużycie przepustowości. Minecraft nie zjada dużo ruchu. 50 graczy generuje około 10-20 Mbps. Jeśli widzisz 500+ Mbps przy 50 graczach, to nie są gracze.

Packet rate (pps) - liczba pakietów na sekundę. Ważne do wykrywania floodów pakietów, które mogą nie generować dużego ruchu objętościowo, ale zabijają CPU obróbką.

Metryki serwera

CPU - obciążenie procesora. Minecraft jest jednowątkowy w głównej pętli, więc patrz na obciążenie konkretnego rdzenia. Jeśli jeden rdzeń jest na 100%, a pozostałe wolne, to normalne działanie MC pod obciążeniem. Jeśli wszystkie rdzenie są obciążone, problem raczej leży w sieci.

RAM - zużycie pamięci. Patrz nie tylko na ogólne zużycie, ale i na zachowanie GC (garbage collectora). Częste pauzy GC zabijają TPS.

Disk I/O - odczyt/zapis na dysk. Minecraft generuje dużo I/O przy zapisywaniu chunków i danych graczy. Jeśli I/O wait jest wysoki, serwer będzie lagał niezależnie od ataków.

Metryki specyficzne dla Minecraft

TPS (Ticks Per Second) - główna metryka zdrowia serwera MC. 20 TPS = idealnie. 18-19 = normalnie. Poniżej 15 = gracze zaczną zauważać lagi. Poniżej 10 = grać nie da się.

Player count - liczba graczy. Nagły skok połączeń bez organicznego wzrostu to czerwona flaga. Ataki botów często wyglądają jak gwałtowny wzrost online.

Chunk loading - prędkość ładowania chunków. Jeśli chunki ładują się wolno, może być to i atak, i problem z dyskiem.

Podstawowe narzędzia Linux

Zacznijmy od tego, co jest na każdym serwerze Linux. Te narzędzia nie wymagają instalacji i dają szybki obraz.

htop: CPU i pamięć w czasie rzeczywistym

htop -p $(pgrep -d, java)

Ta komenda pokaże tylko procesy Java (twój serwer MC). Patrz na:

  • %CPU na każdym rdzeniu
  • RES (realne zużycie RAM)
  • VIRT vs RES (jeśli VIRT jest znacznie większy od RES, to normalne dla Javy)

iftop: ruch sieciowy

sudo iftop -i eth0 -n -P

Flaga -n wyłącza DNS-resolving (przyspiesza działanie), -P pokazuje porty. Zobaczysz, kto wysyła ruch i ile. Jeśli jedno IP generuje gigabity, to atakujący.

nethogs: ruch po procesach

sudo nethogs eth0

Pokazuje, jaki proces zużywa ruch. Jeśli java zjada 500 Mbps, a zwykle 20, coś jest nie tak.

vnstat: historia ruchu

# Instalacja
sudo apt install vnstat

# Statystyki na dzisiaj
vnstat -d

# W czasie rzeczywistym
vnstat -l -i eth0

vnstat zbiera statystyki ruchu i je przechowuje. To pozwala zobaczyć wzorce: "a ile ruchu było wczoraj o tej samej porze?"

Analiza połączeń: netstat i ss

To twoje główne narzędzie do diagnostyki ataków sieciowych. ss jest szybszy niż netstat i preferowany na nowoczesnych systemach.

Ogólne statystyki połączeń

ss -s

Wynik pokaże coś w stylu:

TCP:   1247 (estab 89, closed 1102, orphaned 3, timewait 1098)

Jeśli closed lub timewait są znacznie większe od estab, to znak SYN-flood lub connection flood.

Liczenie połączeń po stanie

ss -tan | awk '{print $1}' | sort | uniq -c | sort -rn

Normalny obraz:

     89 ESTAB
     12 TIME-WAIT
      3 LISTEN
      1 SYN-SENT

Anormalny obraz (atak):

    847 SYN-RECV
     89 ESTAB
    203 TIME-WAIT
      3 LISTEN

847 połączeń w stanie SYN-RECV to klasyczny SYN-flood.

Top adresów IP po liczbie połączeń

ss -tan | awk '{print $5}' | cut -d: -f1 | sort | uniq -c | sort -rn | head -20

Jeśli jedno IP ma 200+ połączeń do twojego serwera, to albo proxy, albo atak. Normalny gracz ma 1-3 połączenia.

Monitoring portu Minecraft

# Liczba połączeń na port 25565
ss -tan state established | grep :25565 | wc -l

# Nowe połączenia na sekundę (uruchamiać dwa razy z interwałem)
ss -tan state syn-recv | grep :25565 | wc -l

Prometheus + Grafana: poważny monitoring

Podstawowe narzędzia są dobre do ręcznej diagnostyki. Ale do stałego monitoringu z historią i alertami potrzebny jest pełny stack.

Instalacja Prometheus

# Pobieramy i rozpakowujemy
wget https://github.com/prometheus/prometheus/releases/download/v2.51.0/prometheus-2.51.0.linux-amd64.tar.gz
tar xvf prometheus-2.51.0.linux-amd64.tar.gz
cd prometheus-2.51.0.linux-amd64

Konfiguracja prometheus.yml:

global:
  scrape_interval: 15s

scrape_configs:
  - job_name: 'node'
    static_configs:
      - targets: ['localhost:9100']

  - job_name: 'minecraft'
    static_configs:
      - targets: ['localhost:9225']
    metrics_path: /metrics

Node Exporter dla metryk systemowych

# Instalacja
wget https://github.com/prometheus/node_exporter/releases/download/v1.7.0/node_exporter-1.7.0.linux-amd64.tar.gz
tar xvf node_exporter-1.7.0.linux-amd64.tar.gz

# Uruchomienie jako serwis
sudo tee /etc/systemd/system/node_exporter.service << EOF
[Unit]
Description=Node Exporter
After=network.target

[Service]
User=prometheus
ExecStart=/opt/node_exporter/node_exporter
Restart=always

[Install]
WantedBy=multi-user.target
EOF

sudo systemctl enable --now node_exporter

Minecraft Exporter

Dla Minecraft jest kilka opcji. Najpopularniejsza to plugin dla Paper/Spigot, który oddaje metryki w formacie Prometheus.

Zainstaluj plugin UnifiedMetrics lub PrometheusExporter na swoim serwerze MC. Po tym metryki będą dostępne na porcie (zwykle 9225).

Typowe metryki, które dostaniesz:

mc_tps 19.8
mc_players_online 47
mc_loaded_chunks 12847
mc_entities_total 8923
mc_memory_used_bytes 4294967296
mc_memory_max_bytes 8589934592

Instalacja Grafany

sudo apt install -y software-properties-common
wget -q -O - https://packages.grafana.com/gpg.key | sudo apt-key add -
echo "deb https://packages.grafana.com/oss/deb stable main" | sudo tee /etc/apt/sources.list.d/grafana.list
sudo apt update && sudo apt install grafana
sudo systemctl enable --now grafana-server

Otwórz Grafanę na porcie 3000, dodaj Prometheus jako źródło danych.

Przydatne zapytania Grafana dla MC

TPS za ostatnią godzinę:

mc_tps

Liczba graczy:

mc_players_online

Nowe połączenia TCP na sekundę (z node_exporter):

rate(node_netstat_Tcp_PassiveOpens[1m])

Zużycie bandwidth:

rate(node_network_receive_bytes_total{device="eth0"}[1m]) * 8

CPU usage po rdzeniach:

100 - (avg by(cpu) (rate(node_cpu_seconds_total{mode="idle"}[1m])) * 100)

Liczba połączeń SYN_RECV:

node_netstat_Tcp_CurrEstab

Spark: profilowanie Minecraft

Spark to profiler stworzony specjalnie dla Minecraft. Pokazuje, co dokładnie spowalnia twój serwer.

Instalacja

Pobierz plik jar z spark.lucko.me i wrzuć do folderu plugins twojego serwera. Zrestartuj serwer.

Główne komendy

/spark tps          - obecny TPS
/spark health       - ogólne informacje o zdrowiu serwera
/spark profiler     - uruchomienie profilowania
/spark profiler --stop  - zatrzymanie i wygenerowanie raportu
/spark gc           - informacje o garbage collection

Monitoring TPS przez Spark

/spark tps

Wypisze coś w stylu:

TPS from last 5s, 10s, 1m, 5m, 15m:
 20.0, 20.0, 19.8, 19.9, 19.7

Jeśli TPS stabilnie poniżej 18, uruchom profiler i zobacz, co zjada zasoby. Podczas ataku TPS zwykle spada gwałtownie, a nie stopniowo. To kluczowa różnica od problemów z pluginami.

Spark i monitoring pamięci

/spark heapdump

Generuje heap dump Javy. To ciężka operacja, nie rób tego podczas ataku. Używaj do analizy post-mortem: "dlaczego serwer padł".

Analiza logów serwera

Logi Minecraft zawierają masę przydatnych informacji, ale trzeba umieć je czytać.

Wzorce wskazujące na atak

# Wiadomości "Can't keep up!"
grep "Can't keep up" logs/latest.log | tail -20

# Liczba ostrzeżeń za ostatnią godzinę
grep "$(date +%H):" logs/latest.log | grep -c "WARN"

# Połączenia za ostatnie 5 minut
grep "logged in with entity" logs/latest.log | tail -50

Wykrywanie botów w logach

Ataki botów zostawiają charakterystyczny ślad w logach:

# Szybkie połączenia/rozłączenia
grep -E "(logged in|lost connection)" logs/latest.log | tail -40

# Jeśli widzisz wzorzec:
# [14:20:01] Player1 logged in
# [14:20:01] Player1 lost connection
# [14:20:01] Player2 logged in
# [14:20:01] Player2 lost connection
# ... i tak setki razy na sekundę - to atak botów

Automatyczny parsing logów

#!/bin/bash
# monitor-logs.sh - prosty monitoring logów MC

LOG_FILE="/home/mc/server/logs/latest.log"
THRESHOLD=50  # połączeń w 60 sekund

while true; do
    COUNT=$(grep -c "logged in" <(tail -n 200 "$LOG_FILE"))
    WARNS=$(grep -c "Can't keep up" <(tail -n 200 "$LOG_FILE"))

    if [ "$COUNT" -gt "$THRESHOLD" ]; then
        echo "[ALERT] $(date): $COUNT logins detected!"
        # Wyślij alert (patrz sekcja o Discord)
    fi

    if [ "$WARNS" -gt 5 ]; then
        echo "[ALERT] $(date): $WARNS 'Can't keep up' warnings!"
    fi

    sleep 10
done

Alerty: Discord, Telegram, Email

Monitoring jest bezużyteczny, jeśli nie dowiadujesz się o problemach. Skonfiguruj powiadomienia.

Discord Webhook

Najprostszy sposób dostawania alertów dla społeczności MC.

#!/bin/bash
# alert-discord.sh

WEBHOOK_URL="https://discord.com/api/webhooks/YOUR_WEBHOOK_ID/YOUR_WEBHOOK_TOKEN"

send_alert() {
    local message="$1"
    local color="${2:-16711680}"  # red by default

    curl -s -H "Content-Type: application/json" \
        -X POST "$WEBHOOK_URL" \
        -d "{
            \"embeds\": [{
                \"title\": \"Server Alert\",
                \"description\": \"$message\",
                \"color\": $color,
                \"timestamp\": \"$(date -u +%Y-%m-%dT%H:%M:%SZ)\"
            }]
        }"
}

# Użycie:
send_alert "High connection rate detected: 482 conn/s" 16711680
send_alert "TPS recovered to 19.8" 65280  # green

Grafana Alerts

W Grafanie można skonfigurować alerty bezpośrednio na dashboardzie. Stwórz Alert Rule:

# W Grafana UI: Alerting -> Alert Rules -> New
# Condition:
#   WHEN avg() OF query(A) IS ABOVE 100
# Query A:
#   rate(node_netstat_Tcp_PassiveOpens[1m])
# For: 30s
# Notification channel: Discord webhook

To wyśle alert na Discord, kiedy liczba nowych połączeń TCP przekroczy 100 na sekundę przez 30 sekund.

Prosty skrypt monitoringu z alertami

#!/bin/bash
# full-monitor.sh - kompleksowy monitoring

DISCORD_WEBHOOK="https://discord.com/api/webhooks/..."
MC_PORT=25565
CONN_THRESHOLD=100
TPS_THRESHOLD=15
CPU_THRESHOLD=90

send_discord() {
    curl -s -H "Content-Type: application/json" \
        -X POST "$DISCORD_WEBHOOK" \
        -d "{\"embeds\":[{\"title\":\"$1\",\"description\":\"$2\",\"color\":$3,\"timestamp\":\"$(date -u +%Y-%m-%dT%H:%M:%SZ)\"}]}"
}

check_connections() {
    local conns=$(ss -tan state syn-recv | grep -c ":$MC_PORT")
    if [ "$conns" -gt "$CONN_THRESHOLD" ]; then
        send_discord "Connection Alert" "SYN_RECV count: $conns (threshold: $CONN_THRESHOLD)" 16711680
        return 1
    fi
    return 0
}

check_cpu() {
    local cpu=$(top -bn1 | grep "Cpu(s)" | awk '{print int($2)}')
    if [ "$cpu" -gt "$CPU_THRESHOLD" ]; then
        send_discord "CPU Alert" "CPU usage: ${cpu}% (threshold: ${CPU_THRESHOLD}%)" 16744448
    fi
}

check_bandwidth() {
    local rx1=$(cat /sys/class/net/eth0/statistics/rx_bytes)
    sleep 1
    local rx2=$(cat /sys/class/net/eth0/statistics/rx_bytes)
    local mbps=$(( (rx2 - rx1) * 8 / 1000000 ))

    if [ "$mbps" -gt 500 ]; then
        send_discord "Bandwidth Alert" "Incoming traffic: ${mbps} Mbps" 16711680
    fi
}

while true; do
    check_connections
    check_cpu
    check_bandwidth
    sleep 5
done

Jak odróżnić atak od legalnego skoku

To ważna umiejętność. Nie każdy skok ruchu to atak. Oto kluczowe różnice.

Oznaki ataku

  • Gwałtowny skok połączeń (z 10 do 500 w sekundy)
  • Dużo SYN_RECV bez przejścia do ESTABLISHED
  • Ruch idzie z wielu IP lub z jednego IP ogromnym strumieniem
  • TPS spada, choć liczba prawdziwych graczy nie wzrosła
  • Wiadomości "Can't keep up!" w logach
  • Połączenia i natychmiastowe rozłączenia (atak botów)

Oznaki legalnego skoku

  • Stopniowy wzrost połączeń (minuty, nie sekundy)
  • Wszystkie połączenia przechodzą do ESTABLISHED
  • TPS spada proporcjonalnie do liczby graczy
  • Brak anomalnego ruchu po bandwidth
  • Gracze realnie grają (czat aktywny, komendy wykonywane)
  • Pokrywa się z wydarzeniem (film na YouTube, rozdanie, event)

Automatyczne rozpoznanie

#!/bin/bash
# detect-anomaly.sh

MC_PORT=25565

# Stosunek SYN_RECV do ESTABLISHED
syn_recv=$(ss -tan state syn-recv | grep -c ":$MC_PORT")
established=$(ss -tan state established | grep -c ":$MC_PORT")

if [ "$established" -eq 0 ]; then
    ratio=999
else
    ratio=$((syn_recv / established))
fi

if [ "$ratio" -gt 5 ]; then
    echo "ATTACK: SYN_RECV/ESTABLISHED ratio is $ratio (${syn_recv}/${established})"
    echo "  -> This looks like a SYN flood"
elif [ "$syn_recv" -gt 200 ]; then
    echo "SUSPICIOUS: $syn_recv SYN_RECV connections"
    echo "  -> Monitor closely"
else
    echo "NORMAL: $syn_recv SYN_RECV, $established ESTABLISHED"
fi

Automatyczna reakcja na ataki

Monitoring bez reakcji jest bezużyteczny. Oto jak zautomatyzować odpowiedź.

Podstawowy skrypt blokowania

#!/bin/bash
# auto-block.sh - automatyczne blokowanie atakujących IP

MC_PORT=25565
CONN_LIMIT=50  # maksimum połączeń z jednego IP
BLOCK_TIME=3600  # blokada na 1 godzinę

# Znajdź IP z przekroczeniem limitu
ss -tan state established dst :$MC_PORT | \
    awk '{print $5}' | cut -d: -f1 | \
    sort | uniq -c | sort -rn | \
    while read count ip; do
        if [ "$count" -gt "$CONN_LIMIT" ] && [ "$ip" != "" ]; then
            echo "Blocking $ip ($count connections)"
            iptables -A INPUT -s "$ip" -j DROP

            # Automatyczne zdjęcie blokady po godzinie
            (sleep $BLOCK_TIME && iptables -D INPUT -s "$ip" -j DROP) &
        fi
    done

Integracja z systemd

Stwórz serwis do automatycznego monitoringu:

sudo tee /etc/systemd/system/mc-monitor.service << EOF
[Unit]
Description=Minecraft Server Monitor
After=network.target

[Service]
Type=simple
User=root
ExecStart=/opt/mc-monitor/full-monitor.sh
Restart=always
RestartSec=5

[Install]
WantedBy=multi-user.target
EOF

sudo systemctl enable --now mc-monitor

Rate limiting przez iptables

Środek prewencyjny, który działa bez monitoringu:

# Ograniczenie nowych połączeń na port MC
iptables -A INPUT -p tcp --dport 25565 \
    --syn -m connlimit --connlimit-above 3 \
    --connlimit-mask 32 -j DROP

# Ograniczenie rate nowych połączeń
iptables -A INPUT -p tcp --dport 25565 \
    --syn -m limit --limit 25/s --limit-burst 50 -j ACCEPT
iptables -A INPUT -p tcp --dport 25565 --syn -j DROP

Integracja z ochroną DDoS

Jeśli twój serwer jest pod ochroną MineGuard, monitoring działa na dwóch poziomach: po stronie ochrony i na twoim serwerze.

Dashboard MineGuard pokazuje metryki sieciowe w czasie rzeczywistym: przychodzący ruch, liczbę połączeń, zablokowane pakiety. Ale monitoring po twojej stronie nadal jest ważny. Ochrona filtruje ataki sieciowe, ale nie widzi, co dzieje się w środku twojego serwera MC: TPS, ładowanie chunków, stan pluginów.

Idealny schemat: ochrona DDoS filtruje ruch na wejściu, twój monitoring pilnuje zdrowia aplikacji.

Podsumowanie: minimalny zestaw na start

Nie trzeba od razu konfigurować Prometheus + Grafany. Zacznij od małego:

  1. Dzisiaj: naucz się ss -s i iftop. Uruchamiaj przy podejrzeniu problemów
  2. W tym tygodniu: zainstaluj vnstat do historii ruchu i Spark do monitoringu TPS
  3. W tym miesiącu: skonfiguruj skrypt z alertami Discord do automatycznych powiadomień
  4. Kiedy będziesz gotowy: rozwiń Prometheus + Grafanę do pełnego monitoringu z historią

Jeśli chcesz się dowiedzieć, co robić, kiedy atak już się zaczął, przeczytaj nasz osobny artykuł. A monitoring pomoże ci zauważyć go, zanim gracze zaczną narzekać.


Chroń swój serwer przed atakami DDoS

Darmowa ochrona z konfiguracją w 5 minut. 1 TB ruchu w zestawie.

Wypróbuj za darmo


Powiązane artykuły