Files
redl-gamepanel/ИЗМЕНЕНИЯ.md
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

246 lines
20 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
**Русский** · [English](CHANGES.en.md)
# HostinPL 5.6 · Что изменено по сравнению с оригиналом
Оригинал: **HostinPL 5.6** в виде «nulled»-сборки (форк `Xopowblu-4EJlOBEK/HostinPL-5.6`),
написанной под Debian 9 и PHP 7.0.
Ниже — всё, что мы поменяли, с указанием файлов и строк. Правки в коде панели лежат в `panel/`.
**Поддерживается и развивается с помощью [REDL.IO](https://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.php``ssh2_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](БЕЗОПАСНОСТЬ.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](ИНСТРУКЦИЯ.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](БЕЗОПАСНОСТЬ.md)).
* Не тестировали платёжные шлюзы живыми платежами и VK-авторизацию.
* Не проверяли работу самих игровых серверов: для этого нужна нода с Docker.
---
**Поддерживается и развивается с помощью [REDL.IO](https://redl.io) — Хостинг с искусственным интеллектом.**