Назад к блогу

Post-Quantum DNSSEC стал реальностью: 2 420-байтный ранбук для операторов игровых бэкендов

Опубликовано 11 сентября 2026 г.
Post-Quantum DNSSEC стал реальностью: 2 420-байтный ранбук для операторов игровых бэкендов Создано с помощью ИИ

Коротко о главном

Узнайте, как Post-Quantum DNSSEC с 2 420-байтными сигнатурами влияет на игровые бэкенды и какие меры нужно применить операторам уже сейчас.

Разрешение DNS стало в 38 раз больше

Каждая миллисекунда, которую ваша игра ждёт разрешения DNS перед подключением игроков к бэкенду, — это миллисекунда, которую они смотрят на экран загрузки. 3 сентября резолвер Cloudflare 1.1.1.1 начал проверять подписи DNSSEC, созданные с помощью ML-DSA-44 — постквантового алгоритма подписи, стандартизированного NIST. Каждая подпись ML-DSA-44 занимает 2 420 байт, что почти в 38 раз больше подписей ECDSA P-256 (64 байта), которые сегодня использует большинство зон с DNSSEC.

Если вы управляете собственными доменами для игрового бэкенда, матчмейкинга, CDN или раздачи ресурсов, это изменение в итоге изменит вашу DNS-инфраструктуру. Конкретные последствия:

  • DNS-ответы, которые сегодня спокойно умещаются в один UDP-пакет, превысят консервативный лимит полезной нагрузки UDP в 1 232 байта
  • Авторитативные серверы будут возвращать усечённые ответы, заставляя клиентов повторять запрос по TCP
  • Зоны с публикацией двух алгоритмов в миграционном окне создают поверхность для downgrade-атак
  • Всё это добавляет задержку уже на первом сетевом переходе у игроков

Это ранбук по обнаружению, смягчению и подготовке к постквантовому DNSSEC в инфраструктуре игровых бэкендов.

Почему игровым бэкендам важно понимать размер подписей DNSSEC

Стена размера UDP

У DNS поверх UDP долгая история ограничения размера пакетов:

Лимит Источник Байт
Исходный максимум DNS over UDP RFC 1035 (1987) 512
Распространённое значение по умолчанию EDNS(0) Разные реализации 1 232
Рекомендованный максимум RFC 9715 (2025) 1 400
Только подпись ML-DSA-44 NIST ML-DSA-44 2 420
Открытый ключ ML-DSA-44 DNSKEY RRset 1 312

Одна подпись ML-DSA-44 сама по себе превышает каждый из этих лимитов, ещё до добавления подписываемого RRset, доменного имени, заголовков и других записей DNSSEC. Использовать фрагментированный UDP ненадёжно — Cloudflare и другие прямо не рекомендуют его с DNS Flag Day 2020, — поэтому практический запас — TCP.

Что падение на TCP стоит вашим игрокам

По данным Cloudflare Radar, примерно 85% запросов к 1.1.1.1 приходят по UDP. По всем сервисам на их платформе Big Pineapple (на которой также работает Gateway DNS) около 60% запросов приходят по UDP. То есть 15–40% DNS-трафика уже идёт по TCP, DoT или DoH — но это добровольные не-UDP-подключения.

Когда UDP не срабатывает и клиент повторяет запрос по TCP, вы платите стандартную цену TCP-handshake: ~1 RTT на SYN/SYN-ACK/ACK ещё до того, как резолвер отправит запрос. Для игрока, которому до вашего бэкенда 80 мс, это ещё 80 мс времени на подключение, прежде чем начнётся аутентификация.

На практике запас TCP происходит между резолвером и авторитетным сервером, и резолвер sert себе результат. Хуже всего, когда:

  1. Кэш пустой — первый за счёт после потери TTL или новый игрок в регионе, где ещё не было трафика
  2. DNSKEY-ответ вашей зоны большой — именно так происходит в период миграции two алгоритмов
  3. Двойные делегирования дают большие ответа — цепочка из 3–4 зон, где каждая содержит и обычные, и постквантовые ключи

Timeouts при запуске сессии уже преследуют мультиплеерные бэкенда и при обычном DNS — мы уже покрывали диагностику проблем таймаутов на уровне сети в Unreal Engine в предыдущем разборе. Постквантовый DNSSEC сделает эти таймауты ещё более частой проблемой, если вы не заложите увеличенные ответы.

Ловушка миграции на двух алгоритмах

ML-DSA-44 нельзя за один день заменить обычными алгоритмами подписи. Зоны должны публиковать и разные (ECDSA/RSA), и постквантовые (ML-DSA-44) ключи для обратной совместимости. В этом окне DNSKEY-ответ зоны может содержать:

  • Обычный открытый ключ (например, 91 байт для ECDSA P-256)
  • Открытый ключ ML-DSA-44 (1 312 байт)
  • Обычную подпись RRset DNSKEY (64 байта)
  • Подпись ML-DSA-44 для RRset DNSKEY (2 420 байт)

Это примерно 3 900 байт только DNSSEC-данных, что уже за любым лимитом UDP. Резолверу придётся использовать TCP.

Поверхность атаки понижения

Вот что превращает эту вопрос из задержки в задачу безопасности. RFC 6840 говорит, что валидаторы «должны принимать любой корректный путь». Это означает, что если зона публикует одновременно и ECDSA, и ML-DSA-44, то резолвер, поддерживающий оба, примет любой из них.

Когда появятся квантовые компьютеры, способные взять ECDSA-ключи, атакующий сможет подделывать ECDSA-only ответы, и постквантовый вимулет резолвер примет их. Вот атака понижения:

  1. Резолвер игрока запрашивает api.your-game-backend.com и получает ответ, подписанный только ECDSA
  2. Резолвер принимает ECDSA-подпись, потому что она проходит через «любой корректный путь»
  3. Атакующий подделал этот ответ с помощью квантонового закрытого ключа
  4. Игрок попадает на сервер атакующего, а не на ваш

Это не теоретическая проблема. Утечка данных использует Star Citizen показала, как одна скомпрометированная инфраструктура может привести к массовой утечке учётных данных. А компрометация на уровне DNS ещё хуже: она перенаправляет каждого игрока, который запрашивает ваш хостname, на управляемый атакующим эндпоинт.

1.1.1.1 закрывает это использованием DS-записи как аутентифицированного сигнала: если DS RRset родительской зоны содержит запись для поддерживаемого постквантового алгоритма, constrictor принудительно применяет более строгую область, требуя хотя бы один корректный постквантовый путь. Если путь ML-DSA-44 не проходит проверку, проверка не выполняется полностью.

Это хорошо — но означает, что зоны, планирующие поддерживать постквантовую защиту, должны публиковать DS-записи ML-DSA-44, и каждое делегирование выше в цепочке тоже должно так делать. Скомпрометированный ключ в любом месте цепочки позволяет атакующему подделать всё ниже него: «взлом один раз — поддел без границ».

Как обнаружить влияние постквантового DNSSEC на вашу инфраструктуру

Шаг 1: Проверьте текущие размеры DNS-ответов

Прежде чем получить результаты, нужны данные как проблема. Используйте dig с флагом +dnssec, чтобы посмотреть текущие размеры ответов для доменов вашей игры:

# Measure current DNSKEY response size for your authoritative zone
dig +dnssec +bufsize=4096 NS your-game-backend.com @your-ns.example.com +short

# Check the full DNSKEY response with size tracking
dig +dnssec +bufsize=4096 DNSKEY your-game-backend.com @your-ns.example.com
# Look at the MSG SIZE stat near the bottom of the output

# Measure a typical A-record query with DNSSEC signatures attached
dig +dnssec +bufsize=4096 A api.your-game-backend.com @your-ns.example.com

Для справки: DNSKEY-ответ с ECDSA P-256 примерно 200–400 байт. Если рядом публикуется ML-DSA-44, ожидайте 3 500–5 000 байт. Запишите текущие значения — они пригодятся для выявления деградации.

Шаг 2: Проверьте, какой алгоритм использует ваша зона

# Extract algorithm numbers from your DNSKEY records
dig +dnssec DNSKEY your-game-backend.com @your-ns.example.com | \
  grep -E "DNSKEY|RRSIG" | awk '{print $5}' | sort -u

Номер алгоритма показывает, какая подпись используется:

Алгоритм Номер Статус
RSA/SHA-256 8 Широко применяется, уязвим к квантовому взлому
ECDSA P-256/SHA-256 13 Самый частый современный выбор, уязвим к квантовому взлому
ED448 16 Квантово-уязвим, но большой (~114 байт)
ML-DSA-44 18 Постквантовый, 2 420 байт, недавно назначен IANA

Если зона сейчас использует алгоритм 13 (ECDSA P-256), вы на самом распространённом современном варианте. Переход на алгоритм 18 для большинства DNS-экосистем пока в стадии планирования, но важно понимать тайм-Line.

Шаг 3: Мониторинг частоты TCP fallback через анализ query-логов

If вы запускаете авторитативные серверы или имеете доступ к логам резолвера, отслеживайте соотношение TCP к UDP. Это самый явный ранний признак ударов о потолок UDP.

#!/usr/bin/env python3
"""
Post-Quantum DNSSEC TCP Fallback Monitor.
Tracks TCP/UDP query ratios from BIND-style query logs
as a proxy for large-response fallback pressure.

Usage:
    python3 pq_dns_monitor.py --log /var/log/named/queries.log --window 2
"""

import re
import argparse
from collections import Counter
from datetime import datetime, timedelta

LOG_PATTERN = re.compile(
    r"(\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2})\.\d+Z"
    r"\s+(\w+)\s+query:\s+\S+\s+(\S+)\s+(\S+)"
)

def analyze_dns_traffic(log_path: str, window_hours: int = 1) -> None:
    cutoff = datetime.utcnow() - timedelta(hours=window_hours)
    transport_counts = Counter()
    rrtype_counts = Counter()
    tcp_by_qtype: Counter = Counter()

    with open(log_path, "r") as f:
        for line in f:
            m = LOG_PATTERN.search(line)
            if not m:
                continue
            ts_str, transport, qname, qtype = m.groups()
            try:
                ts = datetime.strptime(ts_str, "%Y-%m-%dT%H:%M:%S")
                if ts < cutoff:
                    continue
            except ValueError:
                continue

            transport_counts[transport] += 1
            rrtype_counts[qtype] += 1
            if transport == "tcp":
                tcp_by_qtype[qtype] += 1

    total = sum(transport_counts.values())
    if total == 0:
        print("No queries found in the specified time window.")
        return

    tcp_count = transport_counts.get("tcp", 0)
    tcp_pct = (tcp_count / total) * 100

    print(f"=== DNS Transport Breakdown (last {window_hours}h) ===")
    print(f"  UDP: {transport_counts.get('udp', 0):>8} ({100 - tcp_pct:.1f}%)")
    print(f"  TCP: {tcp_count:>8} ({tcp_pct:.1f}%)")
    print(f"  Total: {total:>6}")
    print()

    if tcp_pct > 15.0:
        print(f"  ⚠  ALERT: TCP fallback rate is {tcp_pct:.1f}%.")
        print("     Large DNSSEC responses may be forcing TCP retries.")
        print("     Check whether any upstream zones have added post-quantum keys.")
    elif tcp_pct > 8.0:
        print(f"  ⚡ NOTICE: TCP fallback rate is {tcp_pct:.1f}%. Monitor for increases.")
    else:
        print(f"  ✓  TCP fallback rate ({tcp_pct:.1f}%) is within normal range.")

    # Show which query types incur the most TCP fallback
    if tcp_by_qtype:
        print()
        print("=== TCP Fallback by Query Type ===")
        for qtype, count in tcp_by_qtype.most_common(5):
            pct = (count / rrtype_counts[qtype]) * 100 if rrtype_counts[qtype] else 0
            print(f"  {qtype:<10} {count:>5} TCP / {rrtype_counts[qtype]:>5} total  ({pct:.0f}%)")

    print()
    print("=== Query Type Breakdown ===")
    for qtype, count in rrtype_counts.most_common(10):
        print(f"  {qtype:<10} {count:>6}")

    # Recommendation
    print()
    if tcp_by_qtype.get("DNSKEY", 0) > tcp_by_qtype.get("A", 0) * 0.5:
        print("  ➜  DNSKEY queries have a notably high TCP fallback rate.")
        print("     Your zones or upstream zones may already be publishing")
        print("     large post-quantum keys alongside conventional ones.")


if __name__ == "__main__":
    parser = argparse.ArgumentParser(description="DNS TCP fallback monitor for PQ-DNSSEC readiness")
    parser.add_argument("--log", required=True, help="Path to BIND query log file")
    parser.add_argument("--window", type=int, default=1, help="Time window in hours")
    args = parser.parse_args()
    analyze_dns_traffic(args.log, args.window)

Запускайте это против логов ваших авторитативных серверов регулярно. Если доля TCP-запросов для DNSKEY или DS записей стабильнее выше 10%, ваши резолгеры дошли до UDP-потолка, и причиной почти наверняка будут постквантово-размерные ответа.

Шаг 4: Бенчмарк задержки резолвер — авторитативный сервер

Используйте dnsperf для стресс-теста вашего авторитативного сервера при нагрузке, включая запросы, вызывающие большие ответы:

# Create a test query file focused on DNSSEC-heavy queries
cat > /tmp/dnssec-bench.txt << 'EOF'
your-game-backend.com DNSKEY
your-game-backend.com DNS
api.your-game-backend.com A
match.your-game-backend.com A
assets.your-game-backend.com A
EOF

# Run with 20 concurrent clients for 20 seconds
dnsperf -s your-ns-ip -d /tmp/dnssec-bench.txt -l 20 -c 20

Сравните среднюю задержку и показатели усечения по TCP до и после добавления ML-DSA-44 в тестовую зону. Нужны измеримые цифры, а не догадки.

Меры по укреплению DNS для постквантовых ответов

1. Увеличьте размеры буферов EDNS(0) на авторитативных серверах

Ваши авторитативные серверы должны объявлять максимальный размер UDP-полезной нагрузки, который поддерживают. Это не исключает TCP-запас для DNSKEY-ответов — подписи ML-DSA-44 сами по себе слишком большие, — но позволяет ответам без DNSSEC и более мелким подписям оставаться в UDP и ускоряет сигнал об усечении для клиентов.

# BIND 9 — named.conf
options {
    edns-udp-size 1232;
    max-udp-size 1232;
    tcp-fast-open 256;
};

Значение 1 232 байта выбрано конкретно: 1 280 (минимальный MTU для IPv6) − 40 (IPv6-заголовок) − 8 (UDP-заголовок) = 1 232. Это исключает фрагментацию на любых каналах, поддерживающих минимальный MTU IPv6.

# NSD — nsd.conf
server:
    ipv4-edns-size: 1232
    ipv6-edns-size: 1232

TD TCP Fast Open (TFO) на всех серверах под вашим контролем

TCP Fast Open (TFO) позволяет резолверу отправлять DNS-запрос в SYN-пакете и устраняет один круговой цикл при соединении TCP. Это сокращает запасной путь по TCP с ~2 RTT до ~1 RTT.

# Linux: enable TFO for both inbound and outbound connections (mode 3)
sudo sysctl -w net.ipv4.tcp_fastopen=3

# Verify output
cat /proc/sys/net/ipv4/tcp_fastopen
# Expected output: 3

TFO также должно быть включено в вашем DNS-программном обеспечении. BIND 9 (9.18+), Knot Resolver поддерживают TFO. Для Unbound, в последние сборки включён по умолчанию.

Net effect: TCP DNS-запрос, который раньше стоил ~160ms, теперь ~80ms. Это пока хуже, чем UDP (~80), но штраф снижен вдвое.

3. Разрешайте и кэшируйте хосты при старте игры — не во время игрока

Самый эффективный способ снизить задержку DNS в игровых клиентах — не делать DNS-запросы в игровых критических путях. Запрашивайте все хосты бэкенда start-уки в конце загрузки и кэшируйте IP на всё время сессии.

// Unreal Engine C++ — resolve game backend hostnames at startup
// and cache IP addresses so players never wait for DNS during connect

void UGameBackendSubsystem::Initialize(FSubsystemCollectionBase& Collection)
{
    Super::Initialize(Collection);

    // All hostnames the game needs during a session
    TArray<FString> Hostnames = {
        TEXT("api.your-game-backend.com"),
        TEXT("match.your-game-backend.com"),
        TEXT("assets.cdn.your-game-backend.com"),
    };

    ISocketSubsystem* Sockets = ISocketSubsystem::Get();

    for (const FString& Host : Hostnames)
    {
        // Resolve at startup — resolves once, not on first connect
        FResolveInfo* ResolveInfo = Sockets->GetHostByName(
            TCHAR_TO_ANSI(*Host)
        );

        // Block until resolution completes (acceptable during loading screen)
        ResolveInfo->WaitUntilComplete(5.0f);

        FInternetAddr Result;
        if (ResolveInfo->GetErrorCode() == 0)
        {
            Result = ResolveInfo->GetResolvedAddress();
            FString ResolvedIP = Result.ToString(false);
            CachedEndpoints.Add(Host, ResolvedIP);
            UE_LOG(LogGameBackend, Log,
                TEXT("Pre-resolved %s -> %s (cached for session)"),
                *Host, *ResolvedIP);
        }
        else
        {
            UE_LOG(LogGameBackend, Warning,
                TEXT("DNS resolution failed for %s (error %d)"),
                *Host, ResolveInfo->GetErrorCode());
            // Store empty — will re-resolve on demand with exponential backoff
            CachedEndpoints.Add(Host, FString());
        }
    }
}

FString UGameBackendSubsystem::GetResolvedAddress(const FString& Hostname) const
{
    const FString* Cached = CachedEndpoints.Find(Hostname);
    if (Cached && !Cached->IsEmpty())
    {
        return *Cached;
    }
    return Hostname; // Fallback to hostname (will trigger real DNS)
}

Так ваши игроки никогда не ждут DNS при подключении к серверу или загрузке ассетов. Даже если разрешение занимает 200ms из-за TCP prevented и холодного кэша, оно пройдёт незаметно во время загрузки, а не на экране обратного отсчёта матчмейкинга.

4. Используйте DNS-over-HTTPS для инфраструктурных запросов

DoH работает через HTTP/2 или HTTP/3 — транспортные протоколы на TCP или QUIC — и поэтому полностью обходит ограничение на размер UDP. Если бэкенд-серверы, скрипты деплоя или CI/CD пайплайны выполняют DNS-запросы программно, настройте их на DoH:

# Resolve a hostname using Cloudflare's DoH endpoint
# (requires curl 7.76+)
curl -sS \
  "https://cloudflare-dns.com/dns?name=api.your-game-backend.com&type=A" \
  -H "Accept: application/dns-json" | jq -r '.Answer[0].data'

# For Kubernetes pods, configure CoreDNS to forward to a DoH-capable
# recursive resolver. In practice, this means setting upstream to
# a resolver that natively supports DoH, such as 1.1.1.1 or 8.8.8.8

Это особенно важно для health-check скриптов, проверяющих доступность бэкенда, верификации деплоев и контейнерных оркестраций, где поды по умолчанию используют конфиг резолвера ноды.

5. Аудируйте DS-записи и готовность алгоритмов в вашей зоне

If вы управляете своей авторитативной зоной, проверьте, что DS-записи соответствуют текущему алгоритму и что вы не переносите устаревшие данные.

# Check DS records from the parent zone
dig +short DS your-game-backend.com

# Compare with actual DNSKEY data in your zone
dig +short DNSKEY your-game-backend.com

# Use delv to trace the full DNSSEC validation chain
delv +rtrace api.your-game-backend.com A

Если вы видите устаревшие DS-записи для алгоритмов, которые больше не используете, они вызывают лишние fallback-механизмы в резолверах. Удалите их в ближайшее окно технического обслуживания.

Лучшие практики: чек-лист готовности к постквантовому DNSSEC

  1. Замерьте свои DNS-ответы уже сегодня. Запустите dig +dnssce по всей зонам, от которых зависит ваша инфраструктура. Запишите MSG SIZE для DNSKEY, DS и обычных A-запросов. Эти цифры нужны для обнаружения будущей деградации, когда восходящие зоны начнут публиковать постквантовые записи.

  2. Включите TCP Fast Open на каждом отрезке DNS. Один фуфдаментальный флаг ядра сократить задержку TCP fallback на целый round-trip (примерно 80–160 мс в зависимости от географии). Вместе с агрессивным кэшированием DNS это делает TCP fallback почти невидимым для игроков.

  3. Резолвите хостнеймы на старте игры, не во время игрового процесса. Все бэкенд, CDN и матчмейкерые хосты должны разрешаться на экране загрузки и храниться в памяти. Фоновое обновление через несколько минут обрабатывает истечения TTL и не блокирует игровой процесс.

  4. Мониторьте частоту запасного TCP еженедельно. Настройте анализатор логов из стабильного блока выше или его эквивалент. Стабильная доля TCP более 10% для DNSKEY-запросов означает, что размер ответов уже превышает UDP-лимиты. Относитесь к этому как к превышению SLA по задержке.

  5. Спланируйте тайм-Line алгоритмической миграции DNSSEC. Если подписывают собственную зону, начните тестирование ML-DSA-44 на поддомене в staging. Публикуйте ключи обоих алгоритмов и замерьте, как меняется размер ответов. Не ждите квантовой угрозы, пока она яв не появится, — миграция в DNS измеряется годами, а не спринтами. Переход алгоритм — это задача уровня инфраструктуры, потому что безопасность вашей аккаунтов, лидербордов и облачных сохранений зависит от целостности путей резолвата, которые изначально ведут игроков к этим сервисам.

Таймline: когда это важно для вас

Включение Cloudflare 1.1.1.1 проверка ML-DSA-44 — это первое крупное развёртывание резолвера. Примерная хронология:

Период Что происходит
Сейчас (2025) Cloudflare 1.1.1.1 включает валидацию ML-DSA-44; первые адоптеры начинают тесты
2025–2027 Больше резолверов начинают валидацию; зоны публикуют двух алгоритмов
2027–2029 Массовая адаптация зон; резолверы могут вводить жёсткие антиdowngrade-policy
2029+ Cloudflare рассчитывает на полную постквантовую безопасность; обычные алгоритмы считаются небезопасными

Ни один из этих нарушений завтра не сломает ваши игровые серверы. Но направление миграции ясно.

Операторы игровых бэкендов, которые начают подготовку прямо сейчас — кэширование DNS, TFO, аудит алгоритмов зон, мониторинг TCP fallback — заметят, когда переход завершится. А те, кто откладывает, будут отдаждовать задержки TCP fallback и ошибки проверки DNSSEC в момент живого запуска игры, именно когда это труднее всего себе позволить.

Готовы сосредоточиться на разработке игровых забы, а не на бэкенсной инфраструктуры? horizOn берёт на себя аутентификация аккаунта, облачные сохранения, таблицы лидеров и crash-reporting, чтобы вы могли сконцентрировать усилия на DNS, сетевых и защитных слоях, которые требуют внимания. Загляните в документацию horizOn, чтобы увидеть, что уже входит в коробку.


Источник: 1.1.1.1 now supports post-quantum DNSSEC, all 2,420 bytes of it