Назад к блогу

Почему ваши Dedicated Servers зависают: Реальность DDoS Protection для серверов Unreal Engine

Опубликовано 8 апреля 2026 г.
Почему ваши Dedicated Servers зависают: Реальность DDoS Protection для серверов Unreal Engine

Каждый разработчик Multiplayer-игр боится внезапного и необъяснимого зависания сервера. Ваш выделенный сервер работает безупречно со стабильным Tick rate 30, и вдруг, без предупреждения, вся симуляция останавливается. Игроки испытывают Rubber-banding по всей карте, RPCs теряются, и мгновение спустя фатальный Connection timeout завершает матч. Вы можете инстинктивно винить свой последний код Movement replication или сложные физические расчеты, но если ваша база игроков растет, реальность часто оказывается гораздо более зловещей: ваша инфраструктура стала жертвой скоординированной Distributed Denial of Service (DDoS) атаки.

Недавние отчеты сообщества разработчиков Unreal Engine указывают на массовый всплеск организованных DDoS-атак на игровые серверы, особенно затрагивающих масштабные режимы, такие как Battle Royale и кастомные Creative-инстансы. Эти атаки полностью перегружают Network processing thread сервера, что приводит к серьезному Lag, глобальной десинхронизации и, в конечном итоге, к Hard crashes.

Для Indie-разработчиков и AA-студий внедрение надежной защиты Unreal Engine Server DDoS Protection больше не является опциональным — это обязательное требование для любой Live-ops игры. В этом техническом разборе мы проанализируем, как эти атаки манипулируют Netcode движка Unreal Engine, как отличить вредоносный Flood от обычных плохих сетевых условий и какие конкретные шаги можно предпринять для укрепления инфраструктуры вашей игры.

Анатомия краша сервера Unreal Engine

Чтобы понять, как защитить сервер, сначала нужно разобраться, как Unreal Engine обрабатывает входящий сетевой трафик. Unreal использует кастомный протокол на базе UDP, управляемый NetDriver. Поскольку UDP не требует установления соединения, любой клиент в интернете может отправлять пакеты на открытый порт вашего сервера без формального Handshake.

Волюметрические атаки уровня 4 (Layer 4) против прикладных атак уровня 7 (Layer 7)

Большинство сбоев сервера вызвано одним из двух типов сетевых атак:

1. Волюметрические UDP-флуды (Layer 4): Это атака методом грубой силы. Botnet бомбардирует публичный IP-адрес и порт вашего сервера гигабайтами мусорных UDP-пакетов в секунду. Сетевая карта (NIC) сервера и Network stack операционной системы полностью перегружаются. Еще до того, как Unreal Engine получит возможность проанализировать пакеты, у машины заканчивается Bandwidth или прерывания процессора (CPU interrupts) блокируют обработку легитимного трафика игроков.

2. Истощение прикладного уровня (Layer 7): Эти атаки гораздо более коварны. Вместо отправки случайного мусора атакующий использует инструменты Packet capture или модифицированные игровые клиенты для отправки корректно сформированных запросов на соединение Unreal Engine (таких как пакеты NMT_Hello или NMT_Login) или специфического тяжелого RPC-спама. NetDriver принимает эти на вид валидные пакеты и передает их в Game thread для обработки. Процессор сервера загружается на 100%, пытаясь разобрать тысячи ложных Handshakes авторизации, проверить несуществующие билеты сессий или выделить память для сложных строковых параметров в реплицируемых функциях. Поскольку для стандартного Firewall этот трафик выглядит идентично легитимной активности игроков, он обходит базовую DDoS-защиту. Это мгновенно обрушивает Tick rate сервера, вызывая экстремальные телепортации и Rollback-эффекты, которые игроки наблюдают прямо перед тем, как процесс Watchdog принудительно завершит зависший инстанс.

Диагностика атаки: злой умысел или просто плохой Netcode?

Прежде чем предположить атаку, необходимо исключить катастрофические баги Replication. Если один клиент запускает бесконечный цикл RPC-вызовов, это может имитировать DDoS уровня 7. Проверьте логи крашей и метрики. Если вы видите резкие скачки Memory allocation при низком сетевом трафике, возможно, дело в Replication — для решения этой проблемы изучите наше руководство Zero Ping Spikes Complete Freeze The Ultimate Uefn Server Crash Fix Protocol.

Однако, если ваш внешний мониторинг показывает скачок входящего трафика с ~50 Мбит/с до 5 Гбит/с, или если логи сервера фиксируют тысячи сообщений LogNet: NotifyAcceptingConnection с уникальных IP-адресов за считанные секунды, вы имеете дело с организованной атакой.

Укрепление Netcode: реализация Connection Throttling на C++

Хотя полноценная защита от волюметрических DDoS-атак должна происходить на уровне инфраструктуры (о чем мы поговорим позже), вы можете защитить сервер Unreal Engine от истощения уровня 7, внедрив агрессивный Rate Limiting прямо в AGameModeBase.

Переопределив функцию PreLogin, вы сможете перехватывать попытки подключения до того, как сервер создаст полный APlayerController и начнет дорогостоящий процесс загрузки игрока в мир.

Вот надежная реализация на C++ для ограничения частых попыток подключения с вредоносных IP-адресов:

// 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);
}

Почему этот код важен

Эта реализация отслеживает IP-адрес каждого входящего запроса. Если один IP пытается подключиться более 4 раз в течение 60 секунд, сервер активно отклоняет соединение в PreLogin. Отклонение на этом этапе обходится процессору значительно дешевле, чем создание актора, репликация начальных состояний и последующий кик игрока. Этот простой блок кода может стать решающим фактором в выживании сервера при Layer 7 атаке.

Настройка сетевой конфигурации Unreal Engine

Помимо логики C++, файл DefaultEngine.ini содержит критические параметры. Оставлять их по умолчанию — огромная уязвимость. Если атакующий флудит сервер, а лимиты пропускной способности не установлены, сервер попытается обработать все пакеты, мгновенно загрузив процессор на максимум.

Установите строгие границы сетевого трафика в DefaultEngine.ini для 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

Снижение ConnectionTimeout до 15.0 секунд позволит серверу быстро очищать полуоткрытые или мертвые соединения, освобождая память для реальных игроков.

Проблема инфраструктуры: нельзя заблокировать то, что уже пришло

Настройки C++ и INI защитят от прикладных атак, но они бессильны против волюметрических атак уровня 4: к тому моменту, когда Unreal Engine решит сбросить пакет, Bandwidth уже поглощен.

Если Botnet мощностью 10 Гбит/с направлен на сервер с каналом 1 Гбит/с, никакой C++ код не поможет. Канал физически забит. Легитимный трафик не проходит.

Защита от атак Layer 4 требует стратегии на уровне инфраструктуры.

Подход DIY (Своими руками)

Если вы используете свои Bare-metal серверы или EC2-инстансы, вам придется строить защиту вручную:

  1. Настройка Reverse Proxy: Нельзя открывать реальный IP игрового сервера. Используйте UDP Proxy (например, NGINX с модулем stream или HAProxy). Это добавит немного задержки, но скроет IP сервера.
  2. Настройка iptables/nftables: Нужно писать правила для сброса фрагментированных UDP-пакетов и лимитов на уровне ядра.
  3. Покупка Enterprise-защиты: Дорогие сервисы (AWS Shield Advanced, Cloudflare Magic Transit) для очистки трафика до того, как он попадет в ваш дата-центр.

Создание такой архитектуры требует 4-6 месяцев работы DevOps-специалистов. Это огромные затраты для Indie-студии.

Выход из DevOps-ловушки

Это именно тот кошмар, который решают Backend-as-a-Service платформы. В horizOn эта защита уже настроена.

Вместо месяцев настройки iptables наша платформа управляет Edge network за вас. Серверы защищены корпоративным уровнем маршрутизации, который отсекает вредоносный трафик Layer 4 и Layer 7 до того, как он дойдет до игрового процесса. Ваш Tick rate будет стабилен, а игроки — в сети.

4 совета для Indie-разработчиков под атакой

1. Никогда не открывайте IP сервера напрямую: Используйте Matchmaking-сервисы или токены сессий. 2. Строгая валидация сессий: Требуйте криптографический токен (например, JWT) в PreLogin. Это не даст атакующим обходить лимиты простой сменой IP. 3. Ограничьте Tick rate сервера: Не оставляйте NetServerMaxTickRate неограниченным. Зафиксируйте его на 30 Гц. 4. Мониторьте сетевой край (Network Edge): Логи движка не покажут сброшенные пакеты на Firewall. Следите за InBytes на уровне ОС. Внезапный скачок UDP-трафика — признак атаки.

Защита игры — это гонка вооружений. Используя Rate Limiting и современную инфраструктуру, вы гарантируете игрокам стабильный геймплей.

Хотите забыть о проблемах с инфраструктурой? Попробуйте horizOn бесплатно.


Источник: [VERY CRITICAL] Organized DDoS Attacks Causing Server Crashes