Представьте здание с красивым парадным входом: ресепшен, турникеты, табличка с названием сети. А сбоку, у мусорных баков, стоит неприметная дверь, которую когда-то оставили открытой «на время настройки». Для сети Minecraft на Velocity роль парадного входа играет прокси, а боковой двери — прямой адрес backend-сервера, то есть порт Paper, который кто-то когда-то открыл наружу и забыл. Установить Velocity легко. Гораздо важнее понять, что она сама по себе эту боковую дверь не закрывает.
Эта статья про то, почему так происходит, как устроена передача личности игрока от прокси к игровому серверу, какие способы закрыть обходной путь существуют и что нужно проверить, когда в сети появляется третий, четвёртый и следующий узел. Рассмотрим одну простую схему: один прокси и два backend, например «лобби» и «выживание». Конкретных значений конфигурации здесь не будет — только логика и то, что подтверждает документация.
Кто на самом деле проверяет игрока
Чтобы понять риск, нужно посмотреть, где в сети принимается решение «этот человек действительно тот, за кого себя выдаёт». В обычном одиночном сервере Minecraft этим занимается сам сервер: он общается с системой аутентификации и убеждается, что ник принадлежит владельцу лицензии. В сети с прокси порядок другой. Игрок подключается к Velocity, и проверку проводит именно прокси. Дальше он пересылает игрока на выбранный backend и сообщает ему, кто это: имя, идентификатор, свойства профиля.
Отсюда и возникает необходимость в режиме, при котором сам backend проверку входа не выполняет. Он работает как offline mode: не спрашивает внешний сервис, а доверяет тому, что пришло от прокси. Это разумно и удобно: проверка происходит один раз на входе, а не на каждом игровом узле. Но у такого доверия есть очевидное условие: доверять можно только тому, кто имеет право говорить от имени прокси.
Документация Velocity формулирует это прямо: backend за прокси нужно ограничить так, чтобы принимать подключения только от прокси, потому что в offline mode иначе возможна подмена игрока (раздел о защите backend). Иными словами, offline mode на backend — не дыра, а следствие архитектуры. Дырой он становится только тогда, когда к backend может подключиться кто угодно.
Две двери: правильный вход и обход
Разберём два сценария на одной схеме. Есть прокси, к которому подключаются игроки, и два backend — лобби и выживание. Все три процесса могут жить на одной машине или на разных; пока это не важно.
Путь через прокси
Игрок вводит адрес сети. Velocity принимает соединение, проводит проверку входа, выбирает backend по своим правилам и передаёт ему данные игрока. Backend, настроенный на приём этих данных, создаёт игровую сессию с тем именем и идентификатором, которые сообщил прокси. Для игрока всё выглядит как единый мир, в котором можно переходить между лобби и выживанием без повторного входа.
Путь в обход
Теперь допустим, что порт backend выsurvival доступен из интернета. Злоумышленнику не нужно ломать Velocity: достаточно узнать адрес и порт игрового узла. Адреса вроде бы секретом не являются: они остаются в старых конфигурациях, в чужих списках серверов, в скриншотах, в сообщениях «а вот тестовый адрес, заходите». Подключившись напрямую, человек попадает на сервер, который проверку входа не делает, то есть принимает любое заявленное имя. А если он умеет притворяться прокси и передавать данные игрока, то способен выдать себя за любого, включая оператора с правами на сервере.
Обратите внимание на масштаб последствий. Речь не о том, что «кто-то зашёл без проверки». Речь о том, что игровой узел начинает считать идентификатор игрока достоверным, хотя он ничем не подтверждён. Права, привязанные к идентификатору, инвентарь, привилегии, записи в плагинах экономики — всё это опирается на то, что идентификатор означает конкретного человека. Если его можно назначить самому, любая привязка превращается в формальность.
Сравним два входа в таблице.
| Что происходит | Через Velocity | Напрямую на backend |
|---|---|---|
| Кто проверяет вход игрока | Прокси | Никто, если backend доверяет присланным данным |
| Откуда берётся идентификатор | Из проверенной сессии | Из того, что заявил клиент |
| Что видят правила сети | Единую точку входа | Ничего: прокси в цепочке нет |
| Что нужно для защиты | Настроенный прокси | Закрыть сам путь к backend |
Последняя строка таблицы — главная мысль этого раздела. Защита обходного пути не живёт в настройках прокси. Прокси не может запретить подключаться к тому, к чему он не имеет отношения.
Почему forwarding не заменяет закрытую дверь
Здесь возникает естественный вопрос: а как же modern forwarding и forwarding secret? Разве это не защита? Да, механизм передачи данных с общим секретом нужен: он позволяет backend отличить сообщение от настоящего прокси от подделки. Но документация Velocity подчёркивает: modern forwarding не заменяет firewall (защита backend). Это дополнительный слой, а не замена сетевого ограничения.
Почему так? Потому что у них разные задачи. Сетевое ограничение отвечает на вопрос «кто вообще может установить соединение с этим портом». Секрет пересылки отвечает на вопрос «можно ли доверять данным, которые пришли по уже установленному соединению». Если открыт только второй слой, то весь вес защиты лежит на секрете. А он, как любой секрет, может утечь: попасть в репозиторий с конфигурациями, в скриншот, в архив, который кто-то отправил для помощи в чате. Одновременно открытый порт даёт любому желающему бесконечное число попыток и возможность изучать поведение сервера. Закрытый порт избавляет вас от целого класса проблем ещё до того, как секрет понадобится.
Есть и обратная сторона: если закрыто только сетью, но секрет не настроен или одинаков на всех узлах и известен многим, то внутри сети любой скомпрометированный узел может действовать как прокси. Поэтому документация отдельно требует, чтобы forwarding secret оставался секретным. Два слоя защищают от разных ошибок, и убирать один из них потому, что «есть другой», — значит оставлять одну точку отказа.
Один сервер: самый простой способ закрыть дверь
Если прокси и все backend работают на одной машине, у вас есть самое надёжное ограничение: привязать backend к localhost. Тогда игровой узел слушает только внутренний адрес этой машины, и из интернета подключиться к нему физически нельзя: порт просто не существует снаружи. Документация прямо указывает этот вариант для случая одного сервера (защита backend).
В этом подходе красиво то, что вы не полагаетесь на правила firewall, которые легко сломать при очередной правке. Забыли открыть или закрыть порт — не страшно: слушающий адрес сам по себе ограничивает доступ. Наружу смотрит только прокси. Именно для такой схемы удобен небольшой VPS: Velocity и оба backend живут на одном хосте, игроки подключаются к единственному публичному порту, а остальное скрыто.
Практическая сторона вопроса — ресурсы. Прокси сравнительно лёгкий, а вот каждый backend — это отдельный процесс Java со своей памятью. Лобби обычно нагружено слабее, чем игровой мир с плагинами и множеством игроков. Планы MAATRIX можно использовать как отправную точку для теста: от Ba с 1 vCPU и 2 ГБ RAM до Djed с 16 vCPU и 32 ГБ. Но это не обещание ёмкости. Сколько игроков выдержит конкретная связка, покажет только нагрузка вашей сборки. Для схемы «прокси + лобби + выживание» разумно начинать с плана, где память делится между тремя процессами с запасом, а затем смотреть на реальную нагрузку. Если пока нужно развернуть сам игровой сервер, поможет материал о том, как установить и настроить Minecraft на VPS.
Нужен сервер под эту задачу?
Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации Россия, США, Франция и Великобритания. Оплата картой РФ и по СБП.
Несколько узлов: firewall и туннель
Когда игровой узел переезжает на отдельную машину, localhost перестаёт работать: прокси должен достучаться до backend по сети. Теперь порт backend обязан быть доступен, но только одному адресу — адресу прокси. Документация предлагает для разных узлов firewall и, при необходимости, зашифрованный туннель (защита backend).
Смысл правила простой: на машине с backend входящие соединения к порту игрового сервера разрешены только с адреса прокси, а всё остальное отбрасывается. Важная деталь, которую легко упустить: правило нужно ставить на стороне backend, а не только «где-то в панели провайдера, кажется». Проверять надо снаружи: попробуйте подключиться к порту backend с постороннего адреса и убедитесь, что соединение не устанавливается. Настройка, в которой вы уверены, но не проверили её, — это просто предположение.
Туннель добавляет шифрование между прокси и backend. Он нужен там, где трафик между узлами идёт по сети, которой вы не доверяете полностью. Если же машины связаны приватной сетью или вы считаете канал достаточно защищённым, можно ограничиться firewall; решение зависит от вашей модели угроз, а не от абсолютного правила. Но если вы выбираете туннель, помните: он не отменяет ограничение по адресу, а добавляет к нему защиту содержимого.
Здесь важно, чтобы сам прокси оставался единственной публичной точкой. На машинах с backend нет причин принимать подключения откуда-либо ещё, кроме как от него, и, конечно, нет причин открывать порты управления без необходимости.
Что ещё смотрит наружу: порты, которые легко забыть
Закрыв игровой порт, легко решить, что работа закончена. Но у Paper есть и другие параметры, которые влияют на то, что доступно снаружи. В документации по server.properties описано несколько настроек, которые стоит различать, потому что их часто путают (Paper: server.properties).
- enforce-whitelist управляет тем, будут ли исключены игроки, которых нет в белом списке. Это правило допуска на игровом узле, а не сетевая защита: оно работает только после того, как соединение уже установлено.
- enable-rcon включает удалённую консоль. Это ещё один канал управления сервером, и если он включён без необходимости, это ещё одна дверь, которую придётся охранять отдельно.
- enable-status влияет на то, как сервер отображает статус в списке, но не определяет, имеет ли игрок право подключиться. Отключение статуса не закрывает вход, и принимать его за защиту не стоит.
Урок из этого списка один: у каждой настройки свой смысл, и ни одна из них не заменяет ограничение сетевого доступа. Белый список не помешает постороннему установить соединение с портом, а скрытие статуса не помешает ему же в этот порт войти. Если вы ловите себя на мысли «я же отключил статус, значит, сервер не найдут», — это тот самый момент, когда пора вернуться к firewall.
Согласованность forwarding: обе стороны должны говорить на одном языке
Теперь про вторую половину задачи. Даже когда сеть закрыта, прокси и backend должны одинаково понимать, как передаётся личность игрока. Если одна сторона ожидает данные в одном режиме, а другая отправляет в другом, игрок получает либо ошибку подключения, либо, что хуже, неправильный профиль. Типичный признак рассогласования — игрок заходит под неожиданным идентификатором или не может зайти вовсе.
Поэтому настройку нужно рассматривать как пару: режим пересылки и секрет на прокси должны соответствовать тому, что ожидает каждый backend. Секрет не выдумывается заново на каждом узле, но и не публикуется. Практичный порядок такой: сначала решаете, какой режим вы используете, затем задаёте секрет на прокси, затем переносите его на каждый backend безопасным способом — не через открытый чат и не через общий репозиторий.
Обратите внимание на логику последствий. Если backend настроен на доверие, но сеть открыта, игрок может обойти проверку. Если сеть закрыта, но backend ожидает другой режим, никто не сможет зайти вовсе — это неприятно, но безопасно. Поэтому при отладке всегда выбирайте сбой в сторону «не пускать», а не «пускать всех». Особенно прямо здесь следует сказать: не пытайтесь «починить» проблему входа, отключая проверку на backend и оставляя порт открытым. Это превращает техническую неполадку в уязвимость. Сначала закройте обходной путь, затем разбирайтесь с рассогласованием, и только потом проверяйте вход игроков.
Как проверить, что всё сошлось
Проверка состоит из двух независимых тестов, и важно сделать оба:
- Зайти через адрес сети, пройти в лобби и перейти в выживание. Убедиться, что имя и идентификатор игрока совпадают на обоих узлах, а права и инвентарь привязаны к нему корректно.
- С постороннего адреса попытаться подключиться напрямую к порту каждого backend. Соединение не должно устанавливаться. Если оно устанавливается, вы нашли боковую дверь раньше, чем кто-то другой.
Первый тест подтверждает, что парадный вход работает. Второй — что других входов нет. Только вместе они дают картину, а по отдельности вводят в заблуждение: сеть, в которой игроки заходят прекрасно, может быть при этом полностью открыта.
Добавляем следующий игровой узел
Допустим, сеть выросла и нужен третий backend, например креатив или мини-игры. Именно в этот момент безопасность чаще всего ломается не из-за сложной атаки, а из-за привычки: новый узел поднимают быстро, проверяют, что игрок заходит, и считают дело сделанным. Вход действительно работает, потому что работает через прокси. Но порт нового узла по умолчанию может оказаться открытым.
Поэтому добавление узла стоит воспринимать как небольшую процедуру с одним обязательным условием: узел не должен принимать подключения ни от кого, кроме прокси, ещё до того, как в нём окажутся игроки. На одной машине это привязка к localhost. На отдельной — правило firewall с адресом прокси, а при необходимости и туннель. Затем на новый узел переносится тот же режим пересылки и тот же секрет, что у остальных. И только потом узел регистрируется в списке серверов прокси.
Порядок важен. Если сначала зарегистрировать узел, а затем закрывать его, между этими шагами существует окно, в котором он доступен напрямую. Окно может быть коротким, но у открытого игрового порта нет понятия «ненадолго». Если сначала закрыть, а потом подключать, никакого окна нет.
Есть и вопрос ресурсов. Каждый новый узел — это ещё один процесс со своей потребностью в памяти и процессоре. Решение «поднять третий backend на том же VPS» или «вынести на отдельный» зависит от нагрузки, которую вы увидите в тесте. Если вы переносите узел на другой сервер, учтите, что это меняет и схему защиты: вместо localhost появляется сетевое правило, и его нужно сделать частью обычной процедуры, а не разовой настройкой. Отдельный VPS с root-доступом даёт нужный контроль над firewall и сетевыми интерфейсами, а выбор локации из доступных — UK, US, RU и FR — стоит делать исходя из того, где находятся ваши игроки и как расположены узлы относительно друг друга; точное наличие образов и конфигураций проверяется в форме заказа.
Важный нюанс: отдельные VPS сами по себе не делают сеть отказоустойчивой. Если прокси один, то он остаётся единой точкой входа, и его недоступность означает недоступность всей сети, сколько бы backend ни было позади. Это не недостаток схемы, а её свойство, о котором стоит помнить при планировании.
Сводная схема: кто что принимает
Соберём всё воедино на примере нашей сети из прокси и двух backend, в виде таблицы допустимых соединений.
| Откуда | Куда | Разрешено |
|---|---|---|
| Интернет (игроки) | Прокси | Да, это единственный публичный вход |
| Интернет | Backend «лобби» | Нет |
| Интернет | Backend «выживание» | Нет |
| Прокси | Оба backend | Да, с общим режимом пересылки и секретом |
| Любой другой узел | Backend | Нет, если нет явной причины |
Эту таблицу полезно держать перед глазами при каждом изменении сети. Если новая строка в ней выглядит как «интернет → backend: да», значит, вы собираетесь открыть ту самую боковую дверь, и вопрос «зачем» должен получить очень убедительный ответ.
Один вход — это про контроль, а не про удобство
Игроки видят один адрес, и это удобно. Но удобный адрес и контролируемый вход — разные вещи. Первое достигается тем, что вы рассказываете игрокам, куда подключаться. Второе — тем, что к вашей сети нельзя подключиться иначе. Velocity даёт вам механизм единого входа, проверку личности и передачу её на игровые узлы. Закрыть все остальные пути, не дать секрету утечь и согласовать настройки прокси и backend — это уже ваша часть работы.
Поэтому, когда вы в следующий раз откроете схему своей сети, смотрите не на то, сколько там серверов и насколько красив лобби, а на то, сколько путей ведёт к каждому игровому узлу. Правильный ответ для каждого backend — один: через прокси. Всё остальное должно быть закрыто так, чтобы это можно было проверить снаружи.