um host com proteção ddos syn, e ou um programa de bloqueio, como o ataque acontece no socket o flood pode acontecer na hora que o socket se conecta, o atacante pode ficar enviando varias aberturas de conexão, oque vai inundar a fila do seu socket fazendo com que novas conexão não sejam estabelecidas e faz com que os jogadores não consigam logar no seu jogo, se você preferir pode implementar algo no accept do socket.
Exemplo:
defina uma variavel do tipo fd_set e uma array ou vetor de string para armazenar os ips conectados na estrutura do seu servidor de forma que ela seja acessivel no socket exemplo:
no meu caso em cServer.h
typedef struct MyServer {
//socket list
fd_set readfds;
//ip list
std::vector<std::string> IpBlockList;
}stServer
em cServer.cpp
stServer myServer;
em Basedef ou no local que tu achar mais adequado crie um método para verificação
bool CheckIpSpam(char* ip) {
struct sockaddr_in addr {};
int addrlen = sizeof(addr);
bool isflood = false;
bool ipIsBlock = false;
int connectCount = 0;
int maxPending = 3;
//Iterar pelos soquetes pendentes
for (int i = 0; i < sServer.readfds.fd_count; i++) {
SOCKET s = sServer.readfds.fd_array[i];
// Obter o endereço IP do soquete
getsockname(s, (struct sockaddr*)&addr, &addrlen);
// Compare o endereço IP com o que estamos procurando
if (addr.sin_addr.s_addr == inet_addr(ip)) {
//se a contagem de conexão for maior que o maximo permitido
// remove ele da fila e aplica um ip block
if (connectCount > maxPending) {
FD_CLR(s, &sServer.readfds);
Log(SERVER_SIDE, LOG_HACK, "Flood connection. IP: %s", ip);
closesocket(s);
//verifica se o ip ainda não foi bloqueado
if (!ipIsBlock) {
// faz o bloqueio
BlockIp(ip);
ipIsBlock = true;
}
isflood = true;
}
else {
connectCount++;
}
}
}
return isflood;
}
metodo que faz o bloqueio pode ser adicionado tambem no basedef
estamos usando o firewall do windows para efetuar o bloqueio pois seria a unica forma
de não receber mais flood desse endereço
void BlockIp(char* ip) {
HRESULT hr = S_OK;
INetFwPolicy2* pNetFwPolicy2 = NULL;
INetFwRules* pFwRules = NULL;
INetFwRule* pFwRule = NULL;
hr = CoInitializeEx(0, COINIT_APARTMENTTHREADED);
if (FAILED(hr)) {
Log(SERVER_SIDE, LOG_HACK, "CoInitializeEx failed: %lx", hr);
return;
}
// Recupere a política de firewall.
hr = CoCreateInstance(__uuidof(NetFwPolicy2), NULL, CLSCTX_INPROC_SERVER, __uuidof(INetFwPolicy2), (void**)&pNetFwPolicy2);
if (FAILED(hr)) {
Log(SERVER_SIDE, LOG_HACK, "CoCreateInstance for INetFwPolicy2 failed: %lx", hr);
CoUninitialize();
return;
}
// Recupere as regras do firewall.
hr = pNetFwPolicy2->get_Rules(&pFwRules);
if (FAILED(hr)) {
Log(SERVER_SIDE, LOG_HACK, "get_Rules failed: %lx", hr);
pNetFwPolicy2->Release();
CoUninitialize();
return;
}
// Criar uma nova regra de firewall.
hr = CoCreateInstance(__uuidof(NetFwRule), NULL, CLSCTX_INPROC_SERVER, __uuidof(INetFwRule), (void**)&pFwRule);
if (FAILED(hr)) {
Log(SERVER_SIDE, LOG_HACK, "CoCreateInstance for INetFwRule failed: %lx", hr);
pFwRules->Release();
pNetFwPolicy2->Release();
CoUninitialize();
return;
}
// definir as propriedades da regra.
BSTR bstrRuleName = _com_util::ConvertStringToBSTR("BlockIP");
BSTR bstrRuleDescription = _com_util::ConvertStringToBSTR("Block IP address");
pFwRule->put_Name(bstrRuleName);
pFwRule->put_Description(bstrRuleDescription);
pFwRule->put_Protocol(NET_FW_IP_PROTOCOL_ANY);
pFwRule->put_Direction(NET_FW_RULE_DIR_IN);
pFwRule->put_Action(NET_FW_ACTION_BLOCK);
// Converter o endereço IP para BSTR.
BSTR bstrIp = _com_util::ConvertStringToBSTR(ip);
pFwRule->put_RemoteAddresses(bstrIp);
// Adicione a regra à coleção de regras de firewall.
hr = pFwRules->Add(pFwRule);
if (FAILED(hr)) {
Log(SERVER_SIDE, LOG_HACK, "Failed to add firewall rule: %lx", hr);
}
else {
Log(SERVER_SIDE, LOG_HACK, "IP %s blocked.", ip);
}
// limpar toda essa tranqueira.
SysFreeString(bstrRuleName);
SysFreeString(bstrRuleDescription);
SysFreeString(bstrIp);
pFwRule->Release();
pFwRules->Release();
pNetFwPolicy2->Release();
CoUninitialize();
}
agora onde esta o accept do seu socket caso não tenha voce adiciona.
{
SOCKADDR_IN acc_sin{};
int Size = sizeof(acc_sin);
int tSock = accept(ListenSocket, (struct sockaddr FAR*) & acc_sin, (int FAR*) & (Size));
//aqui vamos armazenar dados do socket que fez a conexão
// bem junto o ip que vai ser a forma que vamos identificar o atacante
FD_SET(ListenSocket, &sServer.readfds);
//armazena o ip na estrutura do socket do server
snprintf(Socket.IP, 16, "%s", inet_ntoa(acc_sin.sin_addr));
if(CheckIpSpam(inet_ntoa(acc_sin.sin_addr))){
Log("IP %s tentou se conectar ao servidor, mas esta na lista de ip's bloqueados.", Socket.IP);
}
}
o std::vector<std::string> IpBlockList; seria para tu armazenar os ips bloqueados para vc salvar em algum lugar para seu controle de ips bloqueados, e até mesmo para desboquer ips.
Atenção: isso é um exemplo de como voce poderia fazer manualmente, não é para copiar e colar no seu servidor achando que vai funcionar.
a ideia aqui é capturar as conexões por ip, definir um limite de conexões pendentes por ip, cuidado que um limite baixo voce pode pegar jogadores que não estejam atacando, por isso repito isso é um exemplo para talvez te dar uma ideia.
talvez seu exe precise de permissão de admin para conseguir executar a rotina de bloqueio no firewall
voce vai precisar da lib netfw