MAATRIX GAMES / Блог / Протокол A2S и запросы статуса сервера

Протокол A2S и запросы статуса сервера

MAATRIX GAMES

Когда серверлист или Discord-бот показывает "12/32 игроков, карта de_dust2, пинг 34 мс" — никто не заходит в игру, чтобы это узнать. Это работает протокол A2S: один UDP-пакет туда, один обратно, и вы знаете всё о сервере, не тратя игровой слот и не проходя авторизацию. Разберём, как это устроено под капотом, где применяется и на что обратить внимание, если ваш сервер вдруг "не виден" в статистике.

Что такое A2S и откуда он взялся

A2S — это Source Server Query Protocol, разработанный Valve для движка Source ещё во времена Half-Life/Counter-Strike и дожившый без больших изменений до Source 2 и CS2. Название расшифровывается как "Any-to-Server" — по сути, любой клиент может послать серверу короткий UDP-запрос и получить структурированный ответ со статусом, не устанавливая игровое соединение и не проходя никакой аутентификации.

Протокол оказался настолько простым и удобным, что его переиспользовали далеко за пределами Source-игр. Rust, ARK: Survival Evolved, 7 Days to Die, Squad, Insurgency, Left 4 Dead 2, Team Fortress 2, Garry's Mod, Mordhau — все они либо построены на Source/Source 2, либо намеренно реализовали A2S-совместимый query-интерфейс, чтобы попадать в те же серверлисты и утилиты мониторинга. Это принципиально отличается от, например, RCON — там нужен пароль и канал для управления сервером; A2S — это read-only и без авторизации, он не даёт никакой власти над сервером, только публичную информацию.

Как устроен запрос на уровне пакетов

A2S работает поверх UDP — без установки соединения, без хендшейка, без гарантии доставки. Клиент отправляет один пакет, сервер (если жив и отвечает) шлёт один пакет назад. Это осознанный выбор Valve: TCP с его тремя рукопожатиями избыточен для того, чтобы раз в 30 секунд спросить "сколько там игроков", а UDP позволяет тысячам ботов одновременно опрашивать тысячи серверов без накладных расходов на поддержание соединений.

Любой A2S-запрос начинается с заголовка простого пакета — четырёх байт 0xFF 0xFF 0xFF 0xFF. Дальше идёт однобайтовый код запроса и, если нужно, дополнительные данные. Например, запрос A2S_INFO — это заголовок плюс байт 0x54 и ASCII-строка "Source Engine Query" с нулевым байтом на конце.

Дальше возможны два сценария:

  • Сервер отвечает сразу — присылает пакет с нужными данными.
  • Сервер требует challenge — отвечает пакетом с кодом 0x41 и 4-байтовым числом-челленджем. Это защита от спуфинга и от использования сервера как усилителя в UDP-амплификационных DDoS-атаках (когда злоумышленник подделывает IP жертвы в запросе, а сервер шлёт ответ — часто больше по размеру, чем запрос — уже жертве). Клиент должен переслать тот же запрос, но уже с этим числом в конце пакета, и только тогда получит настоящий ответ.

Для новых A2S_INFO-запросов challenge обычно не обязателен, а вот для A2S_PLAYER и A2S_RULES сервер почти всегда его требует — так что рабочая реализация клиента должна уметь пройти этот цикл "запрос → challenge → повторный запрос → ответ", а не рассчитывать на прямой ответ с первого раза.

Поскольку это UDP, пакет может потеряться в пути в любую сторону — сети не гарантируют доставку. Любой корректный A2S-клиент обязан работать с таймаутом (обычно 1-3 секунды) и быть готовым к тому, что ответа просто не будет — это не обязательно значит, что сервер упал, иногда это просто потерянный пакет или временная перегрузка сети.

Нужен игровой сервер?

MAATRIX GAMES — 45+ игр, деплой за минуты, DDoS-защита, автобэкапы. Тарифы от 399 ₽/мес.

Создать сервер

Три типа запросов: INFO, PLAYER, RULES

У A2S три основных типа запроса, и у каждого своя польза:

A2S_INFO (запрос 0x54, ответ 0x49) — самый частый и самый лёгкий. Возвращает:

  • версию протокола;
  • название сервера и текущую карту;
  • название игры/папки мода и человекочитаемое имя игры;
  • Steam AppID;
  • текущее число игроков, максимум слотов, число ботов;
  • тип сервера (выделенный/listen-сервер/прокси-SourceTV) и ОС;
  • защищён ли паролем, включён ли VAC;
  • версию сборки сервера;
  • опционально — порт, SteamID сервера, данные о SourceTV, теги (sv_tags) и GameID для игр на Source 2.

Именно A2S_INFO показывает серверлистам и ботам online/max и название карты — это то, что видит игрок, когда листает список серверов в браузере.

A2S_PLAYER (запрос 0x55, ответ 0x44) — список игроков онлайн прямо сейчас: индекс, ник, счёт (score) и время нахождения на сервере в секундах. Полезно для табло "кто сейчас играет" на сайте или в Discord-embed, но требует challenge почти всегда и чуть тяжелее для сервера при частом опросе — не стоит дёргать его каждую секунду.

A2S_RULES (запрос 0x56, ответ 0x45) — набор пар "ключ-значение", которые сервер сам решает публиковать: обычно это часть серверных cvar'ов или кастомные значения, которые выставляет мод/плагин (например, у Rust или ARK через них можно вытащить информацию о режиме, версии карты, модификаторах). Используется реже — в основном специализированными инструментами и некоторыми серверлистами для фильтрации по игровому режиму.

Где применяется A2S на практике

Серверлисты и браузеры серверов. Steam-браузер серверов Source-игр, сторонние сайты вроде GameTracker и BattleMetrics, внутриигровые списки community-серверов — все они массово опрашивают A2S_INFO по спискам IP:порт, чтобы показать актуальный онлайн и пинг раньше, чем игрок вообще подключится.

Discord-боты статуса сервера. Если у вас уже настроен Discord-бот для управления сервером, то блок с живым статусом ("онлайн 14/40, карта — Ba6yka") почти наверняка сделан именно через A2S-опрос раз в 30-60 секунд, а не через RCON — RCON тут избыточен и требует хранить пароль в конфиге бота, тогда как A2S публичный и не требует авторизации вообще.

Системы мониторинга и аптайм-чекеры. Внешние сервисы и самописные скрипты, которые шлют алерт, если сервер "отвалился" или "стух" (не отвечает N проверок подряд), обычно строятся на том же принципе: периодический A2S_INFO-запрос с таймаутом. Это дешевле и информативнее банального ICMP-пинга — вы сразу видите, жив ли именно игровой процесс, а не просто отвечает ли хост на сеть. Если вас больше интересует внутренняя диагностика лагов и просадок тикрейта уже во время игры, а не внешняя доступность — это отдельная тема, разобрана в статье про мониторинг TPS и лагов.

Как проверить A2S вручную и через библиотеки

Реализовывать протокол руками ради простой проверки статуса почти никогда не нужно — для всех популярных языков есть готовые библиотеки, которые берут на себя формирование пакетов, challenge-цикл и парсинг ответа. Для Python из известных — python-a2s, для Node.js — gamedig (умеет не только A2S, но и десятки других query-протоколов разных движков) и steam-server-query.

Пример на Python с python-a2s (pip install python-a2s):

import a2s

address = ("203.0.113.10", 27015)

# Базовая информация: название, карта, онлайн
info = a2s.info(address, timeout=3.0)
print(f"{info.server_name} | {info.map_name} | "
      f"{info.player_count}/{info.max_players} | ping {info.ping*1000:.0f} ms")

# Список игроков онлайн
players = a2s.players(address, timeout=3.0)
for p in players:
    print(f"{p.name}: score {p.score}, {p.duration:.0f} sec on server")

# Кастомные правила сервера (если сервер их публикует)
rules = a2s.rules(address, timeout=3.0)
print(rules)

Библиотека сама обрабатывает challenge-редирект и повторную отправку запроса — вам не нужно вручную парсить байты 0x41. Если хотите проверить сервер вообще без кода — есть готовые онлайн-чекеры статуса Source-серверов, которые под капотом делают ровно тот же A2S_INFO-запрос, только через веб-форму.

Быстрая ручная проверка через netcat малополезна для A2S — протокол бинарный, а не текстовый, так что "потыкать телнетом" как в случае с RCON-подобными интерфейсами не получится. Для отладки удобнее написать 10-строчный скрипт на a2s/gamedig или воспользоваться сетевым сниффером вроде Wireshark с фильтром udp.port == 27015, чтобы увидеть сырые пакеты запроса и ответа.

Query-порт и файрвол: частые грабли

Вот здесь чаще всего и теряют полдня на "почему сервер не виден в статистике, хотя игроки заходят нормально". Дело в том, что не все игры отвечают на A2S на том же порту, на котором принимают игровой трафик:

  • Большинство современных Source/Source 2 игр (CS2, TF2, Left 4 Dead 2, Garry's Mod) обслуживают A2S на том же UDP-порту, что и основной игровой трафик — если сервер доступен игрокам, он обычно доступен и для запроса статуса.
  • Rust традиционно разносит порты: игровой UDP-порт (по умолчанию 28015) и отдельный порт для App/Query (по умолчанию на единицу выше, 28016) — оба задаются параметрами запуска и оба должны быть открыты, иначе бот или серверлист не увидит статус, даже если игроки заходят без проблем.
  • ARK: Survival Evolved/Ascended так же использует отдельный QueryPort (классически 27015) вдобавок к игровому порту (7777) — если проброшен только игровой порт, A2S просто не достучится.
  • 7 Days to Die и ряд других игр с отдельным query-интерфейсом ведут себя аналогично — сверяйтесь с конфигом конкретной игры, какие порты она слушает под запросы статуса.

Практический вывод: при настройке файрвола на своём VPS или при заказе сервера у хостера всегда открывайте оба UDP-порта, если игра их разносит — не только игровой, но и query. Если у вас арендован сервер и статус не отображается в серверлистах при живых игроках — это первое, что стоит проверить: точный номер query-порта в конфиге игры и правило в файрволе именно под UDP (TCP-правило тут не поможет, протокол работает только через UDP).

Ещё одна частая причина "невидимости" — DDoS-защита или анти-спуфинг на стороне хостинг-сети, которая режет нетипичные UDP-пакеты или ограничивает частоту запросов с одного источника. Если статус то появляется, то пропадает при частом опросе — возможно, сработал троттлинг, а не проблема самого сервера.

Нужен игровой сервер?

MAATRIX GAMES — 45+ игр, деплой за минуты, DDoS-защита, автобэкапы. Тарифы от 399 ₽/мес.

Создать сервер

Частые вопросы

Нужен ли пароль или логин для A2S-запроса?

Нет, протокол публичный и не аутентифицированный — это принципиальное отличие от RCON. Любой может опросить статус любого публичного сервера, если знает его IP и порт.

Почему сервер не отвечает на A2S, хотя я захожу в него нормально?

Чаще всего — закрыт отдельный query-порт в файрволе (актуально для Rust, ARK и подобных игр с раздельными портами), реже — включена защита от спуфинга/DDoS, которая блокирует нетипичный трафик опроса.

Можно ли через A2S управлять сервером — кикать игроков, менять карту?

Нет, A2S строго read-only. Для управления нужен RCON — это другой протокол, с паролем, разобран в отдельной статье про RCON.

A2S_INFO и A2S_PLAYER — можно ли опрашивать раз в секунду?

Технически да, но не стоит: частые запросы создают лишнюю нагрузку на сервер и с большей вероятностью попадут под анти-спам защиту. Для серверлиста и Discord-статуса вполне хватает интервала 30-60 секунд.

Что делать, если challenge приходит, а второй запрос всё равно без ответа?

Убедитесь, что вы отправляете challenge-число ровно в том формате, в котором его прислал сервер (little-endian, как есть), и что второй пакет уходит с того же UDP-сокета/порта, с которого шёл первый — некоторые серверы проверяют источник.