Files
redl-gamepanel/ИЗМЕНЕНИЯ.md
T
redlandClaude Fable 5 b6c93514e3 HostinPL 5.6 указан в заголовке каждого документа и в описании репозитория
Из названий было не видно, какая панель лежит в основе. Теперь версия стоит
в H1 всех документов и галерей, а в начале README (обоих) добавлена строка об
оригинале: HostinPL 5.6, авторы Samir Shelenko и Alexander Zemlyanoy, писалась
под Debian 9 / PHP 7.0. Нумерация версии оставлена от оригинала.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-01 05:42:58 +00:00

20 KiB
Raw Blame History

Русский · English

HostinPL 5.6 · Что изменено по сравнению с оригиналом

Оригинал: HostinPL 5.6 в виде «nulled»-сборки (форк Xopowblu-4EJlOBEK/HostinPL-5.6), написанной под Debian 9 и PHP 7.0.

Ниже — всё, что мы поменяли, с указанием файлов и строк. Правки в коде панели лежат в panel/.

Поддерживается и развивается с помощью REDL.IO — Хостинг с искусственным интеллектом.


1. Панель запущена на современном PHP

Оригинал написан под PHP 7.0. На PHP 8 часть кода падала насмерть. Сейчас панель работает на PHP 8.4: обход всех 21 раздела (главная, сервера, новости, статус, тикеты, веб-хостинг и вся админка) даёт 200 на каждом и ноль ошибок в логе.

Файл Было Стало
engine/engine_ftp/elFinder.class.php:4497 utf8_encode() — функция удалена в PHP 8.2, файловый менеджер падал с фатальной ошибкой Обёрнута в function_exists(), фолбэк mb_convert_encoding($str,'UTF-8','ISO-8859-1')
application/views/admin/checksys/index.php:22 apache_get_modules() — существует только в Apache с mod_php, под nginx раздел «Проверка системы» отдавал 500 Обёрнута в function_exists(), иначе проверка по REQUEST_URI
application/views/admin/index.php:215 $item['invoice_ammount'] использовался после foreach, при пустом списке счетов — Undefined variable Проверка isset()
application/models/users.php:199-206 $city[1], $country[1], $countryCode[1] без проверки совпадения регулярки Проверки isset()
application/controllers/common/loginheader.php:35 $_GET['ref'] без isset isset() + приведение к (int)

Что оказалось ложной тревогой

Библиотека phpseclib 1.x в составе панели использует create_function(), удалённую в PHP 8. Выглядело как блокирующая проблема, но проверка показала: phpseclib не подключается ни одним include во всей панели — это мёртвый код. Связь с игровыми нодами идёт через нативное расширение php-ssh2 (engine/libs/ssh2.phpssh2_exec). Ничего чинить не потребовалось.

Так же безопасен get_magic_quotes_gpc() в elFinderConnector.class.php:320 — он закрыт условием version_compare(PHP_VERSION,'5.4','<') && ..., и на PHP 8 до вызова дело не доходит.


2. Капча выключена и управляется из админки

Раньше капча была вшита жёстко: без валидных ключей Google войти в панель было невозможно, на форме висело «ERROR for site owner: Invalid site key». Теперь появился флаг captcha_enable в application/config.php (по умолчанию 0 — выключена).

Бэкенд. Во все четыре валидатора добавлена строка if($this->config->captcha_enable != '1') return $result; перед проверкой капчи:

  • application/controllers/account/login.php — вход
  • application/controllers/common/loginheader.php — регистрация и форма обратной связи (2 места)
  • application/controllers/tickets/create.php — создание тикета

Вёрстка. Пять виджетов капчи (4 в views/common/loginheader.php, 1 в views/tickets/create.php) обёрнуты в <?php if(@$captcha_enable == '1'): ?>. Скрипт Google api.js подключается только при включённой капче. Все вызовы grecaptcha.reset(...) заменены на window.grecaptcha && grecaptcha.reset(...) — иначе при выключенной капче JavaScript падал в обработчиках ошибок и формы переставали отвечать.

Админка. В views/admin/settings.php, вкладка «Прочие настройки», добавлен блок «Защита от ботов (reCAPTCHA v2)»: переключатель Выключена/Включена и поля Site key и Secret key.

Проверено в обе стороны: при выключенной капче вход и регистрация проходят и пользователь реально создаётся в базе; при включённой — свежая сессия получает «Подтвердите, что вы не робот!» и виджет возвращается на страницу.

Осторожно при добавлении своих настроек. Механизм сохранения настроек ищет строки конфига по подстроке (strpos). Поэтому флаг назван captcha_enable, а не captcha: строка captcha содержится в recaptcha и secret_recaptcha, и сохранение перезаписало бы не тот параметр. Новые ключи не должны быть подстрокой существующих.


3. Закрыты уязвимости

Кратко (подробно с кодом — в БЕЗОПАСНОСТЬ.md):

  • Две SQL-инъекции, доступные без авторизации в application/models/users.php (createAuthLog()): в журнал входов без экранирования попадали пароль из формы и IP из заголовка CF-Connecting-IP, который вообще не проверялся. Все значения теперь проходят через $this->db->escape() / (int), заголовок проверяется filter_var(..., FILTER_VALIDATE_IP).
  • Пароли в открытом виде: login.php писал реальный пароль в таблицу authlog при каждой попытке входа, включая неудачные. Убрано.
  • XSS в скрытом поле ref формы регистрации — добавлен htmlspecialchars().
  • Запрос к геосервису ip-api.com выполняется только для валидного IP и с urlencode().

4. Установщик переписан с нуля

Оригинальный install был опасен на любой современной системе:

  • echo "deb ... stretch main" > /etc/apt/sources.listзатирал список репозиториев и заменял его на Debian 9, после чего apt ломался
  • ставил php7.0 и жёстко правил /etc/php/7.0/apache2/php.ini
  • переводил MariaDB на bind-address = 0.0.0.0 без единого предупреждения
  • работал только при /etc/issue.net == Debian9, иначе просто отказывался запускаться
  • пароли и токены генерировал, но нигде не сохранял — их можно было только записать с экрана
  • при любой ошибке продолжал работу: все команды заканчивались на > /dev/null 2>&1

Новые скрипты:

install-panel.sh — nginx, PHP 8.x (версия определяется автоматически), MariaDB, база со случайным паролем, конфиг, планировщик, сторож автозапуска, создание администратора и финальная проверка, что страница входа действительно отдаётся с формой. Идемпотентен: повторный запуск не затирает уже загруженную базу. Креды пишутся в /root/.redl-panel-credentials (chmod 600). set -euo pipefail — при ошибке скрипт останавливается, а не делает вид, что всё хорошо.

install-node.sh — Docker из официального репозитория, сборка образа, каталоги /home/cp/gameservers/files, группа gameservers, MariaDB для баз игровых серверов, SteamCMD, ProFTPD, настройка sshd с откатом конфига, если sshd -t не проходит. Перед началом проверяет, может ли Docker вообще работать на этой машине (unshare -Ur), и честно предупреждает, если нет. В конце печатает готовые данные для подключения локации и команды файрвола.

Ни один из скриптов не трогает /etc/apt/sources.list.


5. Образ игровых серверов пересобран

Оригинальный docker/Dockerfile.original-stretch собран на debian:stretch, а репозитории Debian 9 отключены с 2023 года — образ больше не собирается, apt-get update внутри падает.

Новый docker/Dockerfile — на Debian 12 (bookworm), но обязательно с тегом debian:stretch: это имя жёстко прописано в коде панели (application/models/servers.php:642, docker create ... debian:stretch), менять его без правки панели нельзя.

Что внутри: 32-битные библиотеки (SA-MP, CRMP, MTA, старые CS собраны под i386), screen для консолей, Java для Minecraft, Node.js 20 для RAGE:MP, gdb для разбора крашей. Node.js берётся из NodeSource по HTTPS с проверкой ключа, а не как раньше.


6. Работа без systemd

Панель штатно рассчитана на systemd. В контейнерных VPS его нет, поэтому добавлены сторожа на cron: /usr/local/bin/hostinpl-guard (панель) и /usr/local/bin/gamenode-guard (нода). Раз в минуту (нода — раз в 2 минуты) они проверяют MariaDB, PHP-FPM, nginx, Docker и cron и поднимают то, что упало; плюс задание @reboot для подъёма после перезагрузки.

Живость панели определяется HTTP-запросом к странице входа, а не поиском процесса по имени — поиск по шаблону ловил бы собственную командную строку сторожа.


7. Планировщик

Оригинал прописывал 9 заданий на публичный домен панели. Теперь они ходят на 127.0.0.1 (не зависит от DNS и внешней доступности) и получают таймауты -m, чтобы зависший запрос не копился в процессах.

Грабля с токеном. Токен планировщика нельзя выцеплять из конфига простым grep "'token'" — под это же условие попадает строка 'yk_password1' => 'token', и в URL уезжают два значения через перевод строки, после чего задания молча не работают. В установщике токен пишется напрямую при генерации конфига.


8. Языки интерфейса: русский и английский

Оригинал был только на русском, весь текст вшит в шаблоны. В сборке появился слой перевода:

  • engine/main/lang.php — класс Lang и глобальный помощник t()
  • application/lang/ru.php, application/lang/en.php — словари
  • Порядок выбора языка: параметр ?lang= → cookie langзаголовок браузера Accept-Language → значение по умолчанию из конфига
  • Переключатель (RU / EN) в шапке кабинета, админки и в подвале страницы входа
  • Фразы, которых нет в словаре, остаются на русском — из интерфейса ничего не может пропасть

Перевод применяется к готовому ответу через ob_start(), поэтому 200 файлов шаблонов переписывать не понадобилось, и покрытие сразу распространяется на админку и письма. Замена работает только на границах слов: без этого короткий ключ портил длинные слова («Мод» превращал «Модуль» в «Modуль», «день» делал из «деньги» «dayги»).

Полнота перевода

В словаре 1304 фразы — это весь текст, который панель показывает человеку: кабинет, заказ сервера, управление сервером (консоль с описанием всех RCON-команд, FTP, базы MySQL, файрвол, планировщик задач, автоустановка модов), тикеты, FAQ целиком, вся админка, письма и служебные сообщения планировщика.

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

  • «Русский» — подпись самого переключателя языка;
  • rus => Pyccĸий и ukr => Українська в FAQ — это коды языков игрового сервера, а не интерфейс;
  • регулярное выражение проверки имени /^([А-ЯЁ])([а-яё]{1,15})$/u — код, а не текст.

Отдельно поправлены два подводных камня, которые давали мешанину языков:

  • предлог «в» был отдельной записью словаря и подменялся внутри ещё не переведённых предложений — получалось «at поле имя пользователя». Такие служебные слова переводятся только вместе с фразой;
  • формат даты d.m.Y в H:i содержит русское «в» между датой и временем. Теперь он проходит через t() (31 вызов date() в 20 файлах), и в английском режиме получается 30.07.2026 14:22.

Проверено живым обходом 45 страниц в английском режиме, включая формы создания и скрытые вкладки настроек. Подробности — в ИНСТРУКЦИЯ.md, раздел «Язык интерфейса».


9. Брендинг и даты

  • Год в подвалах: 2020©2026© (views/common/footer.php, views/common/loginheader.php)
  • Название и описание — REDL.IO: application/config.php (description, keywords, mail_sender, mail_from), подвалы, раздел «Проверка системы»
  • Ссылки на сторонние сайты прежнего владельца сборки (hostinpl.ru, osmp.ga) заменены на redl.io
  • Ссылки «Сообщество VK» на чужое сообщество заменены на redl.io (footer.php, views/main/index.php, views/offline/index.php)
  • Все 15 шаблонов писем: шапка «REDL.IO / Хостинг с искусственным интеллектом», подпись «С уважением, Администрация REDL.IO»

Авторские копирайт-заголовки в коде не удалялись — они остались во всех файлах, где были изначально.


10. phpMyAdmin

Панель ссылается на /phpmyadmin из админки. Оригинальный установщик ставил phpMyAdmin через Apache, что на nginx не работало. Теперь он ставится из репозитория дистрибутива и отдаётся самим nginx.

Грабля за обратным прокси. nginx на адрес /phpmyadmin (без слеша) отвечает редиректом и по умолчанию подставляет в него собственный порт, например http://panel.example.com:8095/phpmyadmin/. Если панель стоит за обратным прокси, такой адрес снаружи недоступен и ссылка из админки не открывается. Лечится absolute_redirect off; port_in_redirect off; — это уже прописано в конфиге, который создаёт установщик.


Чего мы НЕ делали

  • Не переписывали хеширование паролей. Панель хранит пароли как MD5 без соли (md5($password), колонка varchar(32)). Переход на password_hash() затрагивает вход, регистрацию, восстановление, смену пароля и требует миграции существующих пользователей.
  • Не переводили создание игровых серверов с Docker на что-то другое.
  • Не удаляли panel/application/public/js/proxy/proxy.php — файл обезврежен, но оставлен как свидетельство (см. БЕЗОПАСНОСТЬ.md).
  • Не тестировали платёжные шлюзы живыми платежами и VK-авторизацию.
  • Не проверяли работу самих игровых серверов: для этого нужна нода с Docker.

Поддерживается и развивается с помощью REDL.IO — Хостинг с искусственным интеллектом.