Skocz do zawartości
SZajbuS

Zabezpieczenie !joinflood z Raksampa

Rekomendowane odpowiedzi

 Witam, jako że niektóre serwery małe które są na hostingach są podatne na crashowanie za pomocą funkcji raksampa !joinflood postanowiłem napisać proste zabezpieczenie na swój serwer który padał ofiarą takich ataków. Kod jest bardzo prosty, wiem że są skrypty które całkiem blokują dostęp z raksampa ale mi było potrzebne tylko zabezpieczenie przed crashem. Wiec potrzebujemy 1 zmienną, zwykła int lub jak ktoś woli może być boolean:

new bool:canConnect = true

która domyślnie będzie miała wartość true.

 

Kod w OnPlayerConnect:

OnPlayerConnect(playerid)
{
  if(canConnect == false)
    {
    Kick(playerid);
    print("Próba crashu serwera raksampem");
    }
  else
    {
    canConnect = false;
    SetTimer("enableConnect", 200, false);
    }
}

Krótkie tłumaczenie, zmienna canConnect decyduje czy gracze mogą się połączyć do serwera czy nie, taki kod blokuje dostęp graczom co 200ms, a raksamp wysyła połączenie domyślnie co 20ms a małe jest prawdopodobieństwo że gracze na małych serwerach będą wchodzili w tak małych odstępach czasu. Więc po próbie połączenie z raksampa po 2 połączeniu flooda wyrzuci użytkownika, a raksamp będzie miał problemy aby połączyć się jeszcze raz i dalej floodować.

 

Potrzebujemy jeszcze tylko publica:

forward enableConnect();
public enableConnect()
  canConnect = true;

który po 200ms znowu włączy możliwość dołączania do serwera. Jeśli coś jest nie jasne to pytajcie, pisałem na szybko a skrypt był testowany na serwerze samp na vps'ie przy połączeniu z 3 komputerów każdy komputer po 3-5 okien raksampa i zsynchronizowany joinflood, bez skryptu serwer padał po 2-5 sekundach, po dodaniu kodu nie udało się go wgl scrashować :-)

Edytowane przez SZajbuS

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

W sumie prawie dobre zabezpieczenie tylko ten timer wygląda niestabilnie, bo jeżeli ktoś w ciągu jednej sekundy wykona 50 albo 100 reconnect-ów? - może przylagować.

Całkiem możliwe, ponieważ w RakSAMP-ie można ustawiać częstotliwości dla poszczególnych ataków.

RakSAMP ma jeszcze pewną inną cechę, którą można wykorzystać (chodzi tu o jego zachowanie w OnPlayerStateChange) za wyjątkiem trybu 1 - z nim trzeba inaczej postępować.

 

W SA-MP 0.3.7-R2 RakSAMP został skutecznie zablokowany - nie daje się nim połączyć z serwerem. Ciekawe na jak długo.

 

Ale można to zabezpieczenie usprawnić, na wypadek gdyby ktoś nie planował przesiadki (np z wersji 0.3z):

new JoinTimer= -1;

OnPlayerConnect(playerid)
{
  if (JoinTimer >= 0)
  {
    Kick(playerid);
    printf("Polaczenie z graczem id: %d zostalo przerwane przez serwer (join-flood)", playerid);
  }
  else JoinTimer= SetTimer("AllowJoin", 200, false);
}

forward AllowJoin();
public AllowJoin()
{
  JoinTimer= -1;
}

Ale i tak rozwiązanie niezbyt dobre, ponieważ nadal może wyrzucać niewinnych graczy.

Edytowane przez PrzMas

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

raksamp w configu domyślnie ma ustawione joinflood co 20ms ja jak testowałem to zmieniłem na 1 ms, crashowało po drugim połączeniu zawsze timer można zmniejszyć nawet do 100ms i ktoś mało obeznany z raksampem nie pomyśli żeby zmienić to w ustawieniach

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

Nie chce mi się nad tym myśleć ale chyba chodzi o to żeby dac graczowi specta i sprawdzić czy stan gracza się zmienił, jeśli nie to kick?

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

A jak myślisz, kiedy będzie najlepiej ustawić mu tryb "spectating"?

Na pewno nie chodzi o to czy się zmienił, bo pewnym jest, że ten stan się zmienia, ale zależy... i w tym miejscu urwę ostatnie 2 słowa.

 

@DOWN

Są ludzie, którzy wolą raczej nic nie ukrywać niż musieć kłamać;

ludzie, którzy wolą raczej kłamać niż nie mieć nic do ukrycia

i ludzie, którzy lubią i kłamstwo i tajemnicę.

Albert Camus

 

Sprawdź sam, a będziesz wiedział najlepiej - musisz przecież coś z czymś porównać żeby mieć pewność.

Jak już się dowiesz to zachowaj to dla siebie.

 

Tylko dodam, że to rozwiązanie może być niewygodne dla pewnych gamemodów, właśnie przez ustawianie tego trybu spectator'a.

Edytowane przez PrzMas

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

Napisz na GG:53511652 ogarne ci Anty na to.

No tak, każdy chce jakoś zarobić, a najlepiej jak najwięcej za jak najmniej, ale twoja propozycja to już kpina w biały dzień.

Wolę wystawić swój pomysł za darmo niż ktoś by miał na nim jeszcze zarobić. [2015-07-24]

// koniec promocji, kto co widziaj to jego - nie chwalić się tym, bo sobie też zaszkodzicie [2015-07-24 21:06]

Zabezpieczenie działa na wszystkie tryby oprócz pierwszego (tj. 2 - 6), no i oprócz zerowego, bo ten (tj. 0) jest tylko do zdalnego logowania się na rcon (znając hasło), które można wyłączyć w server.cfg dodając wpis "rcon 0".

 

Pierwszy tryb (tj. 1) można ograniczyć czasem jednej sekundy, tzn jeżeli w ciągu jednej sekundy od wywołania OnPlayerConnect nie zostanie wywołane zdarzenie OnPlayerStateChange to klient dostaje kick'a jako fałszywy, ale to już trzeba sobie dopisać samemu (i radzę żeby nikt nie próbował na tym zarabiać ;)).

 

Ale mogę się we wszystkim mylić, a kod może być wadliwy lub szkodliwy. [2015-07-24]

 

@mrlolzalot

Już sobie nie zarobisz, chyba, że jesteś w stanie przebić darmowy kod.

 

            Pozdrawiam :D

Edytowane przez PrzMas

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

Mrlolzalot, osoba która straszyła mnie DDoSem chce pomagać za nic, o luju, cud. :-) 

 

@do moderatora:

proponuje usunąć wiekszość posztów, zostawić tylko post PrzMas żeby nie robić spamu w temacie

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

dzięki bardzo, napisz odrębny poradnik, serio przyda się to ludziom bo ja bym na to nie wpadł :)

Żadnych poradników, zresztą to jest trochę za małe na poradnik - mam lepsze rzeczy na poradniki, ale wszystko w swoim czasie.

 

Trochę mi się śmiać chce z Ciebie ponieważ ja na niczym nie zarabiam no ale Okej niech Ci będzie że zarabiam.

Po publikacji przeze mnie kodu wycofałeś swoją propozycję (modyfikując post), a przy takim obrocie sprawy nie zarobisz złamanego grosza i o to mi właśnie chodziło, teraz można się śmiać :D

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

Zależnie od sposobu ataku zabezpieczenie można zrobić na różne sposoby, w przypadku gdy wysyłany jest pakiet RPC_ClientJoin (z informacjami od gracza takimi jak nick, serial itd) jest wtedy wywoływany callback OnPlayerConnect za każdym razem, lecz nie OnPlayerDisconnect (jeśli dobrze wyczytałem to Kalcor zabezpieczył to w którejś tam wersji 0.3.7, ale nie interesuje się już zbytnio sampem)

Zabezpieczyć to można tak że już po pierwszym razie gracz wyleci z banem, sposób bardzo prosty: przy połączeniu na danym slocie ustawiamy jakąś zmienną na np. true, a w OnPlayerDisconnect ustawiamy znowu na false. Przy poprawnym wyjściu gracza, za kazdym razem w OnPlayerDisconnect zmienna będzie miała wartość false, w przypadku ataku będzie miała ona wartość true:

new bool:pConnect[MAX_PLAYERS];
 
public OnPlayerConnect(playerid)
{
    if(pConnect[playerid])
    {
        // zmienna nie została wyczyszczona
        Ban(playerid);
        return 0; // żeby nic więcej nie wykonywać bo gracza już w tym momencie niema
    }
    else pConnect[playerid] = true;
   
    return 1;
}
 
public OnPlayerDisconnect(playerid, reason)
{
    pConnect[playerid] = false;
    return 1;
}

 

W przypadku gdy są to w 100%  normalne nowe połączenia (nowi gracze, a nie spamowany pakiet RPC_ClientJoin z jednego slotu) to zabezpieczenie Szajbusa wydaje się ok (siema, tak przy okazji) chociaż nie wiem czy do końca, bo normalni gracze wtedy nie wejdą. Jedyne co bym w nim zrobił to wyrzucił timery, można to spokojnie zrobić na GetTickCount i będzie to dużo bardziej optymalne i dokładne:

new lastConnectTimestamp; // zmienna w której przechowywany jest timestamp pobrany z funkcji GetTickCount()
 
public OnPlayerConnect(playerid)
{
    if((GetTickCount() - lastConnectTimestamp) < 200)
    {
        printf("próba ataku");
        Kick(playerid);
        return 0;
    }
  
    lastConnectTimestamp = GetTickCount();
    return 1;
}

 

Najzwyklejszego RakSAMPa można "wykryć" na wiele sposobów, chociażby ustawiając mu jakiś poziom życia (SetPlayerHealth) i po jakimś czasie sprawdzenie go (nie od razu, bo musi zostać wysłana synchronizacja)

Jest tez pewien inny bardzo skuteczny sposób którego jeszcze nie próbowałem, ale nie zamierzam o nim nikomu mówić bo nie ja na niego wpadłem.

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach
Jest tez pewien inny bardzo skuteczny sposób którego jeszcze nie próbowałem, ale nie zamierzam o nim nikomu mówić bo nie ja na niego wpadłem.

I bardzo dobrze, bo tak będzie lepiej dla wszystkich, nawet dla tych, którzy chcieliby inaczej - nie wszyscy muszą wszystko wiedzieć.

Edytowane przez PrzMas

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

  • Przeglądający   0 użytkowników

    Brak zarejestrowanych użytkowników przeglądających tę stronę.

×