Привет, Хабр! Когда я был мелкий, и трава зеленее, провайдеры всегда выдавали не белый, а «серый» адрес. Да, он менялся при каждом подключении, но всегда можно было открыть порт и поиграть с корешами в ту же CS 1.6 или Minecraft. Время прошло, и сейчас, чтобы получить белый IP, нужно пройти три круга ада. И то не факт, что дадут. Или: «Купите наш тариф за миллион денег, тогда дадим». Но не про то пошёл разговор.
Предыстория: от идеи к прототипу
Всё началось с того, что мы с коллегами по работе решили собраться и поиграть в CS 1.6. Желающих много, а вот чтобы все были в одном месте — уже не получается. И тогда меня посетила мысль: а что если сделать приложение, чтобы, потягивая пивко, можно было открыть игровой сервер для друзей? А не качать какие‑то Hamachi, ngrok и прочее, а потом ещё 15 минут настраивать порты, пока пиво остывает.
Примерно через полгода я переехал в новую квартиру, и у провайдера просто не было белых IP‑адресов. Так и появился сначала проект с пробросом портов. Идея была простая: купить дешёвый VPS и развернуть своё приложение‑сервер, к которому коннектился бы клиент, и по туннелю пробрасывались порты.
Тут можно сказать: «А зачем новые велосипеды? Изобрели WireGuard — бери и пробрасывай». Но:
Протоколы VPN блокируются некоторыми провайдерами
Нужно идти на VPS и там делать отдельный проброс через iptables, что не вяжется с идеей «создать сервер за 1 минуту»
Первый прототип на Go
После нескольких дней с ChatGPT и кучи тестов был написан сервер и клиент на Go, который это всё позволял делать. Вышло супер: поддерживались протоколы UDP и TCP, проброс нескольких портов.
Но консольный вариант выглядел так себе. Нужно было помнить все адреса, порты, команды, делать батники под каждую игру. И в тот момент посетила мысль: а что если это всё автоматизировать и довести до одной кнопки «Подключиться»?
Так и родился проект PortPlay.
От консоли к GUI
Далее была разработка бэкенда для регистрации, авторизации, просмотра доступных прокси и многого другого. Как бэкенд был более‑менее готов, я приступил к реализации приложения.
Так как консольный клиент был на Go, GUI‑версию тоже было решено писать на Go. Нативного GUI у этого языка нет, и пришлось смотреть варианты. Понравился Wails, потому что по факту ты пишешь сайтик на React, и это будет твоим интерфейсом — что очень удобно.
Первая версия была такая:

Что, согласитесь, не очень привлекательно. Но постепенно интерфейс преображался и стал похож на нормальную программу.
Как на самом деле работает подключение
Отдельно остановлюсь на том, как клиент подключается к прокси‑серверу и какая логика при пробросе портов.
При нажатии «Подключиться» клиент стучится на наш бэкенд.
Бэкенд генерирует уникальный токен сессии, привязанный к ID аккаунта и к конкретному прокси‑серверу. Выбор прокси осуществляется на основе пре‑чека: клиент получает от бэкенда список доступных серверов с их актуальной метрикой (пинг и текущее количество активных юзеров). Клиент выбирает сервер с минимальным временем ответа, при этом отсекая перегруженные узлы.
Клиент подключается к одному из прокси‑серверов и передаёт этот токен.
Прокси‑сервер валидирует его (делает быстрый запрос на бэкенд или проверяет JWT‑подпись, если токен подписан заранее).
Если валидация проходит — прокси поднимает туннель и начинает маршрутизировать TCP/UDP‑трафик. Если нет — соединение сразу рвётся.
Первая проблема: детектирование Minecraft
Первая версия поддерживала только Minecraft, и тут было немножко сложновато детектить порты:
Порт всегда рандомный, если делать сервер через игру
У процесса нет нормального имени — все процессы Minecraft или что‑то другое будут java.exe
Нужно было что‑то посложнее, чем просто мониторить процесс. В итоге проверок было несколько:
Процесс
Порт
Папка, в которой исполняемый файл
Параметры запуска (если можно считать)

Первый факап: DPI и блокировки
После релиза первый пользователь нашёлся через Яндекс.Поиск, и у него, естественно, не получилось создать сервер. Оказалось, что из России к некоторым зарубежным серверам просто нет доступа вообще — любой коннект рвётся, будь то UDP или TCP.
Исследуя поведение и анализируя трафик через Wireshark, было видно, что соединение устанавливается, пропускает примерно 600 байт трафика и резко обрывается. Очень похоже на поведение ТСПУ с DPI‑правилами.
Разочарованию не было предела: первый пользователь и такой факап.
Решение
Подумав, решил, что нужно разделять прокси‑серверы на Россию/СНГ и другие страны. На бэкенде добавил эндпоинты:
/en — выдают только зарубежные прокси
/ru — прокси, которые находятся в пределах СНГ
После такого решения было видно, что у людей начало всё работать. Радости не было предела!
Рост и баги
В первые дни была куча багов и ошибок, релизы выходили чуть ли не каждый день. Идёшь и думаешь: «А что будет, если так сделать?»
Например: пользователь создал сервер, вышел из мира Minecraft, потом зашёл. Думаешь — всё будет работать, но технически он выключил сервер. Программа это увидела и закрыла соединение. А при включении другого мира он запустил его на другом порту.
И таких мелочей была куча.
Масштабирование: добавляем игры
После приведения программы в более‑менее нормальный вид нужно было что‑то делать дальше. В этот момент было примерно 150 зарегистрированных пользователей, что сильно удивило за 2 недели. В основном приходили с поиска Яндекс с запросами:
«Как открыть порт»
«Как создать свой сервер»
и тому подобное
Пока железо горячо, решил добавить другие игры: CS 1.6, CS2 и Terraria, потому что они тоже популярные.

Как ни странно, в эти игры тоже начали люди играть. Если в процентном соотношении:
Minecraft — 80%
CS 1.6 + CS2 — 10%
Terraria — 10%
После решил к основному сайту сделать раздел «Гайды», что ещё докинуло трафика. Теперь из поиска приходили люди, которые конкретно писали «как создать сервер Terraria» или «CS».
На этот момент было около 500 зарегистрированных пользователей и уникальных в день примерно 30–50.
Серверы из программы
Логичным следующим шагом было добавить создание серверов из самой программы. Чтобы, если ты играть не хочешь, а например, друзья могли — не нужно было держать игру запущенной.
Для CS всё было просто — их сервера запускать можно было прямо из папки с игрой. А вот с Minecraft и Terraria были вопросики.
Minecraft
У Minecraft есть как официальные сервера на Java, так и кастомные. Кастомные более оптимизированные и имеют поддержку плагинов — жирный плюс в сравнении с официальными.
В итоге для Minecraft был выбран форк официального сервера Paper + плагины к нему.

Плагины просто устанавливались устанавливая галочки, так же программа проверяет есть ли плагины на нужную версию сайта и если нет появляется уведомление что плагин данный сервер не поддерживает.

После копания их сайта и в целом механики получения того самого сервера в JAR выяснилось, что разные версии сервера Minecraft требуют разную версию Java!
Когда понял что если делать уведомления типа «поставьте такую версию Java», «вот тут и тут скачайте» — это не вариант. В итоге программа сама смотрит, какие версии Java есть, и если для сервера ни одна не подходит — она качает portable‑версию Java для запуска сервера.
Terraria
Как ни странно, для Terraria пришлось писать похожий функционал для .NET, потому что там тоже разные сервера требуют разную версию.
После выкатки обновления с серверами заметно подросло число игроков, которые запускают свои сервера не через Minecraft, а через программу.
Новые фичи
В последнем обновлении был расширен функционал для работы с несколькими портами. Поводом послужили два популярных запроса от пользователей:
Плагин Geyser, который позволяет подключаться к Java‑версии Minecraft с Bedrock
Звуковой мод Simple Voice Chat, который позволяет общаться в Minecraft без Discord и прочего
Поскольку архитектура программы уже поддерживала многопортовую логику, реализация заняла всего один день. Теперь оба плагина работают стабильно.
Сколько стоит инфраструктура
Отдельно хочу рассказать про экономику проекта, потому что это одна из первых вещей, о которых спрашивают. Цифры на самом деле оказались приятнее, чем я ожидал на старте.
Ядро проекта (бэкенд + база данных) Лежит на отдельном сервере. Тут крутится API, авторизация, генерация токенов, учёт пользователей и PostgreSQL с данными. Стоимость — $20/мес.
Прокси‑серверы Это сами «туннели», через которые идёт игровой трафик. Стоимость зависит от региона:
СНГ‑ноды — ближе к $4/мес
Европа/США — ближе к $7/мес
Если брать среднее, выходит около $6 за сервер в месяц. Сейчас в работе 10 прокси‑серверов (5 СНГ + 5 Европа/США), итого $60/мес.
Итого
~$80 в месяц на всю инфраструктуру. Для проекта с 1500 пользователями и 13 500+ сессиями — это, на мой взгляд, очень гуманно. Серверы на Go действительно оказались крайне нетребовательными: даже после месяца аптайма каждый прокси не вылезает за 20 МБ по RAM. Для сравнения, WireGuard‑туннель с одним клиентом на таком же железе кушает больше ресурсов.
Что дальше?
В планах расширять список игр и дать игрокам возможность самим открывать нужные порты.
