Minecraft serverio apsauga nuo botų su iptables pagalba

edited December 2019 in Serverio saugumas
Pastaruoju metu padaugėjo kenčiančių nuo botų kurie užkemša žaidiminį serverį bejungiant į jį didelius kiekius botų iš skirtingų ip adresų (naudojama kogero ar proxiai ar tiesiog kažkokie serveriai). Šioje pamokoje paaiškinsiu kaip galima apsisaugoti nuo tokio tipo atakų su iptables (linuxiniu firewallu). Visu pirma reikia suprasti bent minimaliai kaip veikia TCP (minecraft serveris veikia ant TCP 25565 porto) protokolas tam, kad būtu galima užriboti ataką, papasakosiu paviršutiniškai nes nemanau, kad kažkas labai nori gilintis į tai kaip veikia tcp protokolas. Besijungiantis naujas žaidėjas (o tiksliau pradedant naują TCP sesiją) kiekvienas klientas (klientas tai žaidėjas) siunčia pasisveikinimo paketą į serverį tam, kad užmegsti naują susijungimą (pilnai TCP sesijai užmegsti yra reikalingi trys paketai ir tai vadinama 3 way handshake) ir tas paketas yra vadinamas SYN paketu. Kadangi syn paketai yra privalomi užmegsti tcp sesijai tai mes ribodami tcp syn paketų skaičių į 25565 portą taip pat galime užriboti ir naujai besijungiančiu žaidėjų skaičių per nurodytą laiką skaičių PVZ:

Ši taisyklė nustatys maksimalią ribą 10 syn paketų į 25565 portą per sekundę su išsiplėtimu iki 10 paketų.
iptables -A INPUT -p tcp --dport 25565 --syn -m limit --limit 10/s --limit-burst 10 -j ACCEPT
iptables -A INPUT -p tcp --dport 25565 --syn -j DROP

To kaip ir pakaktu jeigu ne kenkėjai kurie paleidžia šį floodą ir palieka dienai - keliom - kas tada nutinka?
Esančių žaidėjų kurie yra jau pasijunge į serverį neišmes ir jie nieko nepajaus (nes jie jau užmezgė sesiją anksčiau), bet kadangi vyksta ataka kuri siunčia nemažai syn paketų, o iptables praleidžia tik 10 per sekundę naujiems žaidėjiems serverį rodys kaip išjungta.

Kaip išvengti? Galima pasinaudoti ip adresų sąrašu kurį suteikia ripe ir iš to sąrašo atrinkti Lietuviškus ip adresus ir juos prileisti prie serverio ko pasekoje visi lietuviški ip adresai atakos metu matys serverį veikianti. Lietuviškus ip adresus sudėti į prileidžiamus yra gana saugu, nes Lietuovje nėra tiek daug proxy serverių, kad paveiktu viso serverio darbą.

Taigi priename prie galutinio varianto koks turėtu būti eiliškumas:
1: Nutriname visas esamas taisykles
2: Atsisiunčiame iš Ripe šiai grupei priklausančių ip adresų sąrašą
3: bash skriptuko pagalba atsirenkame Lietuviškus ip adresus ir praleidžiame syn iš jų
4: Prisileidžiame syn paketus iš norimų papildomų ip adresų
5: Uždedame syn paketų ribojimą 10 per sekundę
6: Uždraudžiame visus kitus syn paketus

Ir galutinis variantas atrodo štai taip:

#flushinamos visos kitos iptables taisyklės
iptables -F
iptables -X
iptables -t nat -F
iptables -t nat -X
iptables -t mangle -F
iptables -t mangle -X
iptables -P INPUT ACCEPT
iptables -P FORWARD ACCEPT
iptables -P OUTPUT ACCEPT


#sugeneruojama data pagal ripe standartą
failas=`date --date="1 day ago" '+%Y%m%d'`
#ištrinami visi seni failai darbinėi direktorijoj su ripe subnetais
rm delegated-ripencc-*
#siunčiame failą su visais ripe subnetais
wget ftp://ftp.ripe.net/pub/stats/ripencc/delegated-ripencc-$failas
#ciklas su kuriuo atrinksime lietuviškus ip adresus bei  sugeneruosime subnetus, prileisime subnetus į serverį be ribojimų
for i in $(cat delegated-ripencc-$failas | grep LT | grep ipv4)
do
class=`echo $i | cut -d\| -f4`
mask=`echo $i | cut -d\| -f5`
if [ $mask -eq "256" ]; then
klase=`echo $class"/24"`
elif [ $mask -eq "512" ]; then
klase=`echo $class"/23"`
elif [ $mask -eq "1024" ]; then
klase=`echo $class"/22"`
elif [ $mask -eq "2048" ]; then
klase=`echo $class"/21"`
elif [ $mask -eq "4096" ]; then
klase=`echo $class"/20"`
elif [ $mask -eq "8192" ]; then
klase=`echo $class"/19"`
elif [ $mask -eq "16384" ]; then
klase=`echo $class"/18"`
elif [ $mask -eq "32768" ]; then
klase=`echo $class"/17"`
elif [ $mask -eq "65536" ]; then
klase=`echo $class"/16"`
elif [ $mask -eq "131072" ]; then
klase=`echo $class"/15"`
elif [ $mask -eq "262144" ]; then
klase=`echo $class"/14"`
elif [ $mask -eq "524288" ]; then
klase=`echo $class"/13"`
elif [ $mask -eq "1048576" ]; then
klase=`echo $class"/12"`
elif [ $mask -eq "2097152" ]; then
klase=`echo $class"/11"`
elif [ $mask -eq "4194304" ]; then
klase=`echo $class"/10"`
elif [ $mask -eq "8388608" ]; then
klase=`echo $class"/9"`
elif [ $mask -eq "16777216" ]; then
klase=`echo $class"/8"`
fi
#įdedam accept taisyklę Lietuviškiems ip adresams
iptables -A INPUT -s $klase -p tcp --dport 25565 --syn -j ACCEPT
done

#Prisileidžiam lokalų tinklą jeigu del kokiu nors priežasčių vyksta vidiniai susijungimai
iptables -A INPUT -s 127.0.0.1 -p tcp --dport 25565 --syn -j ACCEPT
#Atkomentuojame apatinę eilutę tik tada kai nustatysite savo serverio ip adresą vietoj SERVERIO_IP_ADRESAS
#iptables -A INPUT -s SERVERIO_IP_ADRESAS -p tcp --dport 25565 --syn -j ACCEPT
#Prileidžiame tele2 kelis subnetus nes tele2 iš labai didelio subneto Lietuvai išskyrė labai mažą dalį ir ta dalis nėra atskiras subnetas (tokių išimčių gali būti ir daugiau)
iptables -A INPUT -s 90.131.32.0/18 -p tcp --dport 25565 --syn -j ACCEPT
#Nustatome maksimalų kieki SYN paketų per sekundę, kiekvienas naujai besijungiantis žaidejas iš pradžių siunčia šitą paketą, jau žaidžiantis nesiunčia
iptables -A INPUT -p tcp --dport 25565 --syn -m limit --limit 10/s --limit-burst 10 -j ACCEPT
#Tam, kad suveiktu ribojimai reikia uždėti taisyklę kuri blokuoja viską kas iki šiol neaprašyta
iptables -A INPUT -p tcp --dport 25565 --syn -j DROP
Tiems kas nesupranta kaip naudotis šiuo kodu:
Nukopijuojate visą tekstą kuris yra pilkesniame fone aukščiau, įdedame į failą, failą įkeliame į serverį ir parašome per putty bash failo pavadinimas. Turėkite omenyje, kad jeigu failą įkėlėte į /root/ katalogą jums reikia rašyti bash /root/failas arba prieštai nueiti į tą aplanką cd /root ir tada bash failas. Turėkit omenyje, kad jeigu failas turi galūnę tarkime .txt tai turite taip ir rašyti bash /root/failas.txt ir nenaudokite notepad ar wordpad nes jie būna palieka šiukšles kurių nemėgsta bash.
Sign In or Register to comment.