Voltar ao Blog

Por que seus Dedicated Servers estão travando: A realidade da DDoS Protection em servidores Unreal Engine

Publicado em 8 de abril de 2026
Por que seus Dedicated Servers estão travando: A realidade da DDoS Protection em servidores Unreal Engine

Todo desenvolvedor de jogos Multiplayer teme o congelamento repentino e inexplicável do servidor. Sua instância dedicada está rodando perfeitamente a uma Tick rate estável de 30, e então, sem aviso, toda a simulação para. Os jogadores sofrem Rubber-banding pelo mapa, RPCs são perdidos e, momentos depois, o fatal Connection timeout encerra a partida. Você pode instintivamente culpar seu código mais recente de Movement replication ou um cálculo complexo de física, mas se sua base de jogadores está crescendo, a realidade costuma ser muito mais maliciosa: sua infraestrutura é vítima de um ataque coordenado de Distributed Denial of Service (DDoS).

Relatórios recentes da comunidade de desenvolvedores Unreal Engine destacam um aumento massivo de ataques DDoS organizados contra servidores de jogos, afetando particularmente modos de larga escala como Battle Royale e instâncias Creative personalizadas. Esses ataques sobrecarregam completamente a Network processing thread do servidor, resultando em Lag severo, dessincronização global e, por fim, Hard crashes.

Para desenvolvedores Indie e estúdios AA, implementar uma proteção robusta de Unreal Engine Server DDoS Protection não é mais opcional — é um requisito obrigatório para qualquer jogo Live-ops. Neste detalhamento técnico, analisaremos como esses ataques manipulam o Netcode da Unreal Engine, como diferenciar um Flood malicioso de condições de rede ruins padrão e os passos concretos que você pode tomar para proteger a infraestrutura do seu jogo.

A Anatomia de um Crash de Servidor Unreal Engine

Para entender como proteger seu servidor, primeiro você precisa entender como a Unreal Engine processa o tráfego de rede recebido. A Unreal utiliza um protocolo personalizado baseado em UDP gerenciado pelo NetDriver. Como o UDP é sem conexão, qualquer cliente na internet pode enviar pacotes para a porta aberta do seu servidor sem um Handshake formal.

Ataques Volumétricos de Camada 4 vs. Ataques de Aplicação de Camada 7

A maioria dos crashes de servidor é causada por um de dois tipos de ataques de rede:

1. UDP Floods Volumétricos (Camada 4): Este é um ataque de força bruta. Uma Botnet bombardeia o endereço IP público e a porta do seu servidor com gigabytes de pacotes UDP inúteis por segundo. A placa de rede (NIC) do servidor e a Network stack do sistema operacional ficam completamente saturadas. Antes mesmo que a Unreal Engine tenha a chance de analisar os pacotes, a máquina fica sem Bandwidth ou as interrupções de CPU esgotam os recursos, descartando completamente o tráfego legítimo dos jogadores.

2. Exaustão da Camada de Aplicação (Camada 7): Esses ataques são muito mais insidiosos. Em vez de enviar lixo aleatório, o atacante usa ferramentas de Packet capture ou clientes de jogo modificados para enviar solicitações de conexão da Unreal Engine formatadas corretamente (como pacotes NMT_Hello ou NMT_Login) ou spam pesado de RPCs específicos. O NetDriver aceita esses pacotes aparentemente válidos e os repassa para a Game thread para processamento. O CPU do servidor sobe para 100% enquanto tenta processar milhares de Handshakes de login falsos, validar tickets de sessão inexistentes ou alocar memória para parâmetros de string complexos em funções replicadas. Como esse tráfego parece idêntico à atividade legítima de jogadores para um Firewall padrão, ele ignora a proteção DDoS básica. Isso derruba imediatamente a Tick rate do servidor, causando os comportamentos extremos de teletransporte e Rollback que os jogadores experimentam logo antes do processo Watchdog encerrar a instância travada.

Diagnosticando o Ataque: É malicioso ou apenas um Netcode ruim?

Antes de assumir que seu servidor está sob ataque, você deve descartar bugs catastróficos de Replication. Se um único cliente disparar um loop infinito de chamadas RPC, isso pode imitar um DDoS de Camada 7. Antes de entrar em pânico, revise seus logs de crash e métricas. Se você notar picos massivos na Memory allocation, mas baixo tráfego de rede, pode estar lidando com um problema de Replication — para orientação sobre isso, confira nosso guia sobre Zero Ping Spikes Complete Freeze The Ultimate Uefn Server Crash Fix Protocol.

No entanto, se o seu monitoramento externo mostrar picos de tráfego de entrada subindo de uma base de ~50 Mbps para 5 Gbps, ou se os logs do servidor mostrarem milhares de mensagens LogNet: NotifyAcceptingConnection de endereços IP exclusivos em questão de segundos, você está lidando com um ataque coordenado.

Fortalecendo seu Netcode: Implementando Connection Throttling em C++

Embora a verdadeira mitigação de DDoS volumétrico deva ocorrer no nível da infraestrutura (que cobriremos em breve), você pode proteger seu servidor Unreal Engine contra a exaustão da Camada 7 implementando um Rate Limiting agressivo diretamente no seu AGameModeBase.

Ao sobrescrever a função PreLogin, você pode interceptar tentativas de conexão antes que o servidor aloque um APlayerController completo e inicie o processo caro de carregar o jogador no mundo.

Aqui está uma implementação robusta em C++ para limitar tentativas rápidas de conexão de endereços IP maliciosos:

// In YourGameMode.h
#pragma once

#include "CoreMinimal.h"
#include "GameFramework/GameModeBase.h"
#include "YourGameMode.generated.h"

UCLASS()
class YOURGAME_API AYourGameMode : public AGameModeBase
{
    GENERATED_BODY()

public:
    virtual void PreLogin(const FString& Options, const FString& Address, const FUniqueNetIdRepl& UniqueId, FString& ErrorMessage) override;

private:
    // Maps to track connection attempts per IP
    TMap<FString, int32> ConnectionAttempts;
    TMap<FString, float> LastConnectionTime;

    // Configuration limits
    const int32 MaxAttemptsPerMinute = 4;
    const float LockoutTimeSeconds = 60.0f;
};
// In YourGameMode.cpp
#include "YourGameMode.h"
#include "Engine/World.h"

void AYourGameMode::PreLogin(const FString& Options, const FString& Address, const FUniqueNetIdRepl& UniqueId, FString& ErrorMessage)
{
    // Always call super first to handle native bans and base logic
    Super::PreLogin(Options, Address, UniqueId, ErrorMessage);

    // If an error was already generated (e.g., server full), exit early
    if (!ErrorMessage.IsEmpty())
    {        return;
    }

    // The Address string usually arrives in the format "IP:Port"
    FString ClientIP;
    FString PortStr;
    if (!Address.Split(TEXT(":"), &ClientIP, &PortStr))
    {        ClientIP = Address; // Fallback if no port is appended
    }

    float CurrentTime = GetWorld()->GetTimeSeconds();

    // Check if this IP is currently in our tracking map
    if (LastConnectionTime.Contains(ClientIP))
    {        float TimeSinceLastAttempt = CurrentTime - LastConnectionTime[ClientIP];
        
        // If they are connecting too fast and have exceeded the attempt limit
        if (TimeSinceLastAttempt < LockoutTimeSeconds && ConnectionAttempts[ClientIP] >= MaxAttemptsPerMinute)
        {            ErrorMessage = TEXT("Connection rate limit exceeded. Please wait 60 seconds.");
            UE_LOG(LogGameMode, Warning, TEXT("DDoS Mitigation: Rejected rapid connection attempt from %s."), *ClientIP);
            return;
        }

        // If the lockout window has passed, reset their counter
        if (TimeSinceLastAttempt >= LockoutTimeSeconds)
        {            ConnectionAttempts[ClientIP] = 0;
        }    }

    // Increment the attempt counter and update the timestamp
    int32 Attempts = ConnectionAttempts.FindOrAdd(ClientIP, 0);
    ConnectionAttempts[ClientIP] = Attempts + 1;
    LastConnectionTime.Add(ClientIP, CurrentTime);

    UE_LOG(LogGameMode, Log, TEXT("Connection validation passed. Attempt %d from %s"), ConnectionAttempts[ClientIP], *ClientIP);
}

Por que este código é importante

Esta implementação rastreia o endereço IP de cada solicitação recebida. Se um único IP tentar se conectar mais de 4 vezes em uma janela de 60 segundos, o servidor rejeita ativamente a conexão em PreLogin. Rejeitar uma conexão aqui é significativamente mais barato em ciclos de CPU do que permitir que a engine spawne um actor, replique estados iniciais e depois chute o jogador. Este simples bloco de código pode ser a diferença entre o seu servidor sobreviver a um ataque de Camada 7 e travar completamente.

Ajustando a Configuração de Rede da Unreal Engine

Além da lógica C++, seu arquivo DefaultEngine.ini contém vários parâmetros críticos. Deixá-los nos valores padrão é uma vulnerabilidade massiva. Se um atacante inundar seu servidor e seus limites de Bandwidth estiverem abertos, o servidor tentará processar tudo, esgotando o CPU instantaneamente.

Você deve estabelecer limites superiores rígidos para o seu tráfego de rede. Abra seu DefaultEngine.ini e aplique estes limites ao IpNetDriver:

[/Script/Engine.Player]
; Limit maximum connection speed to 10 MB/s to prevent single-client bandwidth exhaustion
ConfiguredInternetSpeed=10485760
ConfiguredLanSpeed=10485760

[/Script/OnlineSubsystemUtils.IpNetDriver]
; Maximum data rate allowed per client (in bytes). 100kb/s is usually plenty for an FPS.
MaxClientRate=100000
MaxInternetClientRate=100000

; Cap the server tick rate to ensure predictable CPU load.
NetServerMaxTickRate=30

; Aggressively drop unresponsive clients. Defaults are often too long (60s+).
ConnectionTimeout=15.0
InitialConnectTimeout=15.0

; How often the server expects a keep-alive ping.
KeepAliveTime=0.2

; Limit the number of ports the server will try to bind to upon startup.
MaxPortCountToTry=512

Ao reduzir ConnectionTimeout para 15.0 segundos, seu servidor purgará rapidamente conexões mortas ou semi-abertas geradas por um ataque DDoS, liberando memória e slots de rede para jogadores legítimos.

O Problema da Infraestrutura: Você não pode bloquear o que já chegou

As configurações de throttling C++ e INI detalhadas acima protegerão você contra exaustão da camada de aplicação, mas compartilham uma falha fatal quando se trata de ataques volumétricos de Camada 4: quando seu servidor Unreal Engine decide descartar o pacote, o Bandwidth já foi consumido.

Se um atacante apontar uma Botnet de 10 Gbps para o seu servidor, e seu provedor de hospedagem fornecer apenas uma interface de rede de 1 Gbps, não importa quão otimizado seja seu código C++. Os canais que levam ao seu servidor estão fisicamente entupidos. O tráfego legítimo de jogadores não consegue passar.

Mitigar ataques de Camada 4 requer uma estratégia de defesa no nível da infraestrutura.

A Abordagem "Faça Você Mesmo"

Se você estiver rodando seus próprios servidores dedicados Bare-metal ou instâncias EC2 padrão, terá que construir um pipeline de mitigação manualmente. Isso geralmente envolve:

  1. Configurar um Reverse Proxy: Você não pode expor o IP real do seu servidor Unreal Engine. Você deve rotear o tráfego através de um proxy UDP (como NGINX com o módulo stream ou HAProxy). Isso adiciona um salto de latência, mas permite esconder o IP real da instância.
  2. Configurar iptables/nftables: Você deve escrever regras de Firewall rígidas para descartar pacotes UDP fragmentados e limitar conexões por IP no nível do kernel.
  3. Comprar Mitigação Enterprise: Você tem que comprar serviços de roteamento enterprise caros (como AWS Shield Advanced ou Cloudflare Magic Transit) para filtrar o tráfego malicioso antes que ele chegue ao seu data center.

Construir essa arquitetura baseada em proxy você mesmo exige configurar fleet managers, Load balancers e tabelas de roteamento complexas — facilmente 4 a 6 meses de trabalho especializado de DevOps. É um enorme dreno financeiro e temporal para um estúdio Indie.

Escapando da Armadilha de DevOps

Este é exatamente o pesadelo de infraestrutura que plataformas de Backend-as-a-Service foram projetadas para resolver. Com horizOn, esta infraestrutura de backend blindada já vem pré-configurada.

Em vez de passar meses configurando iptables, nossa plataforma gerencia o Edge network para você. Suas instâncias de jogo estão protegidas atrás de uma camada de roteamento de nível empresarial que identifica e descarta automaticamente o tráfego malicioso antes que ele chegue ao seu servidor Unreal Engine. Isso significa que sua Tick rate permanece estável e seus jogadores legítimos continuam conectados.

4 Boas Práticas para Desenvolvedores Indie sob Ataque

Siga estes princípios fundamentais de segurança para proteger seu jogo:

1. Nunca exponha IPs de servidores diretamente aos clientes: Se um jogador puder ver o IP do seu servidor via Wireshark, o atacante também poderá. Use um serviço de Matchmaking seguro ou tickets de sessão.

2. Implemente uma validação de sessão rigorosa: Não deixe os clientes se conectarem apenas sabendo o IP e a porta. Exija um token criptográfico (como um JWT). Valide este token imediatamente em PreLogin. Isso evita que atacantes burlem seu limite girando IPs.

3. Limite a Tick rate do servidor: Não use NetServerMaxTickRate ilimitado. Trave em um valor estável (30 Hz) para garantir reserva de CPU.

4. Monitore o Edge da rede, não apenas a Engine: Logs da engine não mostram pacotes descartados no Firewall. Você deve ter métricas de Bandwidth de entrada (InBytes) no nível do sistema operacional. Um pico súbito de tráfego UDP sem aumento de jogadores é o principal indicador de um ataque volumétrico.

Proteger seu jogo é uma corrida armamentista constante. Ao implementar Rate Limiting agressivo e utilizar infraestrutura que descarta tráfego ruim no Edge, você garante que seus jogadores tenham a experiência que você planejou.

Pronto para parar de se preocupar com infraestrutura? Experimente o horizOn gratuitamente.


Fonte: [VERY CRITICAL] Organized DDoS Attacks Causing Server Crashes