# Форк 3X-UI KIT (hacker07) — своя сборка и свой канал обновлений Коротко: это [3X-UI KIT](https://github.com/itsnotkubrick/3X-UI_KIT) со своими доработками. Наш код живёт рядом с кодом автора и не ломается, когда автор выпускает новую версию, а серверы ставятся и обновляются **из этого репозитория** — релизы подписываются нашим ключом. ## С чего начать: новый VPS 1. Если нужен свой домен для маскировки — заранее направьте его A-запись на IP сервера и освободите порт 80 (иначе Let's Encrypt не выпустит сертификат). Без домена этот шаг пропускается. 2. Одна команда на сервере (от root) — **дальше скрипт спросит сам**: какие протоколы ставить (Enter — REALITY + AmneziaWG-3.1, «все» — набор автора), какую маскировку и домен, закрывать ли ответ на ping, включать ли автообновления, менять ли порт SSH (Enter — оставить текущий, число — перевести на него), менять ли пароль root: ```bash bash <(curl -fsSL https://git.rukavishnikoff.ru/hacker07/3X-UI_autoVPS/raw/branch/main/scripts/3x-ui-local.sh) ``` Те же ответы можно задать флагами — тогда вопросов не будет: ```bash bash <(curl -fsSL …/scripts/3x-ui-local.sh) --protocols reality,hy2,awg,mtproto --domain vpn.example.com ``` 3. Скрипт делает всё сам: проверяет сервер → скачивает наш релиз и **проверяет подпись `SHA256SUMS` и SHA256 установщика** → запускает установщик автора (панель 3X-UI, **только выбранные протоколы**, сайт-заглушка, маскировка, сертификат, подписка, ufw) → наши вопросы и правки (ping, автообновления, второй порт SSH, пароль root) → `kit fix` → в конце показывает `kit check` и сводку `kit local hardening`. 4. Забрать ссылки и подписку: `kit user link admin` (или адрес подписки из вывода установки). Сомневаетесь в канале — сначала ничего не меняющие режимы: ```bash bash <(curl -fsSL …/scripts/3x-ui-local.sh) --verify-only # только проверка подписи релиза bash <(curl -fsSL …/scripts/3x-ui-local.sh) --dry-run --domain vpn.example.com # план установки ``` ### Флаги установки | Флаг | Что делает | |---|---| | `--protocols список` | какие протоколы ставить: `all`, `minimal` или через запятую — `reality,reality2,hy2,xhttp,ws,trojan,vmess,ss,tuic,wg,awg,awg3,mtproto`. Невыбранные не создаются вообще. Без флага — вопрос, по умолчанию предлагаются **REALITY + AmneziaWG-3.1** (ответ «все» — набор автора) | | `--site N\|random\|off` | сайт-заглушка: конкретный из нашего набора (10 ИТ-сайтов), случайный (по умолчанию) или не трогать авторскую страницу (то же — `--no-site`) | | `--yes` | не задавать вопросы (ping закрывается, автообновления включаются, порт SSH и пароль не трогаются) | | `--harden` | закрыть ответ на ping и включить автообновления без вопросов | | `--domain домен` | свой домен для маскировки: сайт и REALITY маскируются под него (A-запись на сервер, свободный 80) | | `--sni сайт.com` | маскировка под чужой сайт вместо домена | | `--panel-on domain\|ip` | где открывать панель и подписку | | `--ssh-port N` | перевести SSH на порт N (число 1024–65535). Прежний порт сам не закрывается: сначала проверьте вход во втором окне, потом `kit local ssh --close-old N` | | `--no-harden` | не закрывать ответ на ping и не включать автообновления безопасности | | `--no-time` / `--no-check` | не запускать `kit fix` / `kit check` | | `--verify-only` / `--dry-run` | проверить релиз / показать план и ничего не менять | | остальные | передаются установщику автора как есть: `--host`, `--user`, `--port`, `--protocols`, `--restore`, `--multi-port`, `--cert`/`--key`, `--panel-ssl` | Чего скрипт **не** делает (сознательно): `apt full-upgrade` (тянет систему вперёд и может сломать закреплённые панель 3X-UI 3.9.0 и ядро Xray 26.6.27 — вместо него обновления безопасности), автоматическую перезагрузку и смену пароля root (в однострочник пароль не подставляем, он попал бы в список процессов — для этого есть `kit local passwd`). ### Как проверить, что установка удалась ```bash kit check # без ❌: службы, порт 443 (nginx), подписка, маскировка, сертификат kit local hardening # сводка: порты SSH, ответ на ping: deny, ufw активен, автообновления: включены kit local channel # источник — этот репозиторий, ключей в KIT_SIGNERS: 1 (наш) kit local version # версия сборки: 1.2.5 или новее ping # с домашней машины — таймаут: ответ на ping закрыт, это ожидаемо kit user link admin # ссылка подписки; откройте её в браузере ``` Если ставили с доменом, в `kit check` должны быть строки «свой домен … указывает на этот сервер» и «сайт маскировки … отвечает по TLS 1.3 и HTTP/2»; предупреждения про известный сайт на чужом IP быть не должно (это касалось бы вспомогательного XHTTP, у REALITY должен быть ваш домен). ## Команды форка (`kit local`) ```bash kit local help # справка по всем командам форка kit local version # версия, источник обновлений, дата сборки нашего файла kit local channel # откуда берутся обновления и чем проверяется подпись kit local seams # какие швы форка сейчас в установленном /usr/local/bin/kit kit local masking # состояние маскировки (у REALITY должен быть свой домен) kit local hardening # сводка по защите сервера ``` Защита сервера (поведение взято из проекта `StressOzz/vps-setup`, реализация своя и безопаснее): | Команда | Что делает | |---|---| | `kit local site` | поставить случайный сайт-заглушку из нашего набора (10 ИТ-сайтов) и синхронизировать ответ Hysteria2 | | `kit local site --list` / `kit local site 7` / `--show` | список сайтов с номерами / поставить конкретный / какой стоит сейчас | | `kit local ssh 2222` | добавить порт SSH (прежние продолжают работать; порт сначала открывается в ufw, конфиг проверяется через `sshd -t`) | | `kit local ssh --status` | какие порты SSH слушаются сейчас | | `kit local ssh --close-old 2222` | закрыть прежние порты после того, как новый проверен из второго окна | | `kit local ping off\|on\|status` | ответ на ICMP echo: закрыть/вернуть/показать (правилом ufw, видно в `ufw status`) | | `kit local passwd [юзер]` | сменить пароль (спросит дважды, в историю команд не попадёт) | | `kit local passwd --generate` | сгенерировать пароль и показать один раз | | `kit local upgrades on\|off\|status` | автообновления безопасности (только security, без перезагрузки) | К любой правке можно добавить `--dry-run` — покажет план и ничего не изменит. Копии изменённых файлов складываются в `/root/kit-local-backup-<дата>/` (не в `/tmp`). Что `ping off` затрагивает: только ICMP echo. Подписка (HTTPS), панель, REALITY/XHTTP (TCP 443), Hysteria2 (UDP 443) работают как работали; исходящий ping с самого сервера тоже остаётся. Если сервер есть в вашем мониторинге — пробу до него делайте по HTTPS/TCP, а не по ICMP. ## Что где лежит | Что | Где | Правит | |---|---|---| | Наши доработки (команды, хуки) | `scripts/kit-local.sh` | только мы | | Установка одной командой (обёртка) | `scripts/3x-ui-local.sh` | только мы | | Описание «швов» в коде автора | `tools/fork_apply.py` | только мы | | Синхронизация с автором и проверки | `tools/fork-sync.sh` | только мы | | Записи о наших версиях | `FORK-CHANGELOG.md` | только мы | | `README.md` | целиком, включая картинки в `manuals/assets/` | только мы | | Файлы автора (`scripts/kit.sh`, `scripts/3x-ui.sh`, …) | как есть | только автор | Ключевая идея: в файлах автора мы правим только «швы» — несколько констант, одну строку подключения и нормализацию сумм в релизном скрипте. Всё, что мы дописываем по существу, лежит в наших файлах. Швы описаны в одном месте (`tools/fork_apply.py`) и накатываются только на чистое дерево автора; если автор изменил нужную строку — инструмент останавливается и говорит об этом, а не делает полу-патч. ## Ветки и релизы - `upstream` — точная копия ветки автора (`main`), только вперёд. - `dev` — наша сборка: `upstream` + швы + наши файлы; из неё делаются релизы. - `main` — то же состояние плюс документация после релиза (по нему считается «последняя версия»). - релизы — теги `v<номера>`; номер = `<версия автора>.<наш уровень>` (автор 1.2 → наш 1.2.1; после релиза автора 1.3 → 1.3.1). Номер обязан строго расти: `kit update` не принимает откат назад. ## Обновление сервера и канал ```bash kit update --force && kit check # тянет наш релиз из этого репозитория, проверяет нашу подпись ``` Источник файлов — `KIT_RAW` / `kit_ref_raw()` в `scripts/kit.sh` (наш Gitea и наш тег), подпись проверяется ключом из `KIT_SIGNERS` (там только ключ форка). Ночной `kit-update.timer` (03:00) делает то же автоматически — поэтому сервер и должен смотреть в этот репозиторий: иначе наши доработки исчезнут в первую же ночь. Вернуться на канал автора: скачать `scripts/kit.sh` из релиза автора с GitHub в `/usr/local/bin/kit`, затем `kit update --force`. ## Обновление от автора (с рабочей станции) ```bash cd H:/My_Proj/Fork_3X-UI_KIT bash tools/fork-sync.sh # подтянуть автора, перенести наши правки, прогнать проверки # при конфликте — разобрать вручную: инструмент сам ничего не публикует bash tools/release.sh ~/.ssh/3x-ui-kit-fork/release_key # SHA256SUMS + подпись нашим ключом git add -A && git commit -m "Релиз v$(cat VERSION): …" && git tag v$(cat VERSION) git push origin dev v$(cat VERSION) upstream ``` ## Подпись релизов - Открытая часть ключа — `tools/fork-signer.pub` и в `KIT_SIGNERS` (в `scripts/kit.sh`); она же вшита в `scripts/3x-ui-local.sh`, чтобы проверять подпись до запуска установщика. - Закрытая часть — только на рабочей станции владельца (`~/.ssh/3x-ui-kit-fork/release_key`). В репозиторий, CI и на серверы не попадает: кто получит ключ — получит root на всех серверах, которые обновляются из этого репозитория. Пароль на ключ пока не установлен (`ssh-keygen -p -f ~/.ssh/3x-ui-kit-fork/release_key`). - Смена ключа: новый релиз подписывается **старым** ключом, иначе серверы его не примут. ## Грабли, о которых стоит помнить 1. **Ночное автообновление** (`kit-update.timer`, 03:00) перезаписывает `/usr/local/bin/kit` тем, что лежит в настроенном репозитории. Канал и наши правки — один шаг, а не два. 2. **Переводы строк.** Релиз подписывается по суммам рабочей копии, а сервер сверяет их с файлами из Gitea: при `core.autocrlf=true` суммы не сойдутся (CRLF против LF). В клоне должно быть `git config core.autocrlf false` (и `.gitattributes`), проверка есть в `tools/fork-sync.sh`. 3. **Наш файл обязан быть в двух списках** — `FILES=(…)` в `tools/release.sh` и список загрузки `fetch_release()` в `scripts/kit.sh`, иначе после обновления `kit-local.sh` останется старым. 4. **Панель 3X-UI ставится с GitHub** по закреплённой версии и SHA256 — это шаг автора; для установки с нуля серверу нужен доступ к GitHub. 5. **Формат контрольных сумм.** `kit` сверяет имя файла в `SHA256SUMS` строго (`$2 == "путь"`). На Windows `sha256sum` пишет `hash *путь`, и такие релизы `kit update` отклоняет («в подписанном списке нет такого файла»), хотя `sha256sum -c` их принимает. Поэтому `tools/release.sh` приводит список к POSIX-виду **до** подписи, а релизы **v1.2.1–v1.2.4 ставить нельзя** — только v1.2.5+. Проверять релиз надо логикой самого `kit`, а не одной `sha256sum -c`. 6. **Сборка релиза обращается к GitHub** (сверка закреплённых версий панели и ядра). Из домашней сети TLS до GitHub иногда рвётся (`schannel: failed to receive handshake`) — просто повторить запуск. 7. **`README.md` — наш файл целиком.** Авторское описание убрано: иначе человек, открывший репозиторий, читает команду установки **авторской** сборки, ставит по ней и оказывается на авторском канале обновлений — ночное автообновление вернёт его сборку. При обновлении из авторского проекта README конфликтует: берём нашу версию (`git checkout --ours README.md`), авторские правки в нём нас не интересуют. ## Что проверено на сегодня - Релиз `v1.2.5`: подпись сходится с ключом из опубликованного `kit.sh`, строгая сверка сумм `$2 == путь` для `kit.sh`, `kit-sub.py`, `kit-local.sh` — как это делает `kit` на сервере. - Публичный однострочник в режиме `--verify-only` отвечает «подпись сошлась, SHA256 установщика совпал» — проверено снаружи, из домашней сети. - Установка «в бою» на живом сервере пока не прогонялась: сначала её стоит выполнить на новом VPS, посмотрев `--verify-only` и `--dry-run`.