niedziela, 21 października 2012

C++ TFS packet flood protection

Recently I posted the The Forgotten Server Firewall codes on the Premium Board of OTLand.net but noone implemented it in tfs core. I believe that developers are using it on their own servers to gain some advantage over competition.

I don't like this kind of attitude so I decided to release it here.
WARNING: This is not simple copy&paste code. You need to read it carefully and add some variables in files. Ok, you have been warned - so here you are:
Add this function & function's prototype:


bool ProtocolGame
::gotCooldown(Playerplayerint recvbyte)
{
    if(!
player)
        return 
false;
    if(
player->isRemoved())
        return 
false;
    
int64_t tNow time(NULL);
 
    if(
cooldownExceedAttemp g_config.getNumber(ConfigManager::COOLDOWN_EXCEED_ATTEMP)) //20
    
{
        
disconnectClient(0x14"Tried to send too many packets.");
        
std::clog<<"[ DOS ATTEMPT FROM ] "<< player->getName()<<std::endl;
        return 
false;
    }
    if(
cooldownLast != tNow)
    {
        if(
cooldownCounter g_config.getNumber(ConfigManager::COOLDOWN_EXCEED_WARNING)) //5
            
cooldownCounter 0;
        else
        {
            if(
cooldownExceed g_config.getNumber(ConfigManager::COOLDOWN_EXCEED_SECONDS) < tNow//SECONDS
                
cooldownCounter 0;
            else
            {
                
cooldownExceedAttemp++;
                
cooldownCounter g_config.getNumber(ConfigManager::COOLDOWN_EXCEED_WARNING); //5
            
}
        }
        
cooldownLast tNow;
        return 
false;
    }
    else
    {
        
cooldownCounter++;
        if(
cooldownCounter g_config.getNumber(ConfigManager::COOLDOWN_PPS)) //10
            
return false;
        else
            
cooldownExceed tNow;
    } 
    return 
true;
}  
in 
PHP Code:
void ProtocolGame::parsePacket(NetworkMessage &msg)  
before
PHP Code:
        switch(recvbyte)
        {  
add:
PHP Code:
if(recvbyte >= 0x6F && recvbyte != 0x96 && recvbyte <= 0xF1)
            if(
gotCooldown(playerrecvbyte))
                return;  

in:
PHP Code:
bool ProtocolGame::parseFirstPacket(NetworkMessagemsg)  
after
if(g_game.getGameState() == GAMESTATE_SHUTDOWN)
{
getConnection()->close();
return false;
}
add
PHP Code:
cooldownLast 0;
    
cooldownCounter 0;
    
cooldownExceed 0;
    
cooldownExceedAttemp 0;  
and add above in protocolgame.h
And add those config variables from 1st function to the configmanager.


And you can now limit incoming packets based on the character to prevent too fast items moving, or too fast attacking creatures or even too fast using talkactions or items.

Good luck!

1 komentarz: