v1.2.3: установка одной командой (3x-ui-local.sh) — релиз из нашего канала + защита сервера

This commit is contained in:
2026-10-12 19:36:00 +03:00
parent 88af9444c0
commit 2e875aaa2f
9 changed files with 220 additions and 7 deletions
+15
View File
@@ -3,6 +3,21 @@
Здесь записи о наших версиях. Файл автора (`CHANGELOG.md`) мы не трогаем — так обновления
автора не конфликтуют с нашими записями.
## v1.2.3: установка одной командой (`scripts/3x-ui-local.sh`)
* Один скрипт на чистом VPS: проверка сервера → скачивание нашего релиза → проверка подписи
`SHA256SUMS` и SHA256 самого установщика → установщик автора (панель 3X-UI, протоколы,
сайт-заглушка, маскировка, сертификат, подписка, ufw) → наши дополнения → проверка.
* По умолчанию досыпает: закрыть ответ на ping (правилом ufw), включить обновления безопасности,
`kit fix` (время и безопасные починки), в конце `kit check` и сводку `kit local hardening`.
Отключается флагами `--no-harden`, `--no-time`, `--no-check`.
* Второй порт SSH — только по явному флагу `--ssh-port N`: прежний порт продолжает работать,
закрытие — отдельным шагом `kit local ssh --close-old N`. Автоматически доступ не запираем.
* Все флаги установщика автора (`--domain`, `--sni`, `--panel-on`, `--host`, `--restore` …)
передаются как есть; есть `--dry-run` (план без изменений) и `--help`.
* Публичный ключ форка вшит в обёртку — подпись проверяется до запуска чужого кода; при смене
ключа обновляется и здесь, и в `kit`.
## v1.2.2: команды защиты сервера (поведение из StressOzz/vps-setup)
* Новые команды `kit local`: `ssh <порт>` (добавить порт SSH), `ssh --close-old` (закрыть прежние
+8 -1
View File
@@ -44,7 +44,14 @@ git push origin dev v$(cat VERSION) upstream
## Установка и обновление из этого репозитория
```bash
# установка на чистый сервер (вместо команды автора с GitHub)
# установка одной командой (рекомендую): наш релиз, подпись проверяется до запуска установщика,
# в конце — закрытие ping, автообновления безопасности, kit fix и kit check
bash <(curl -fsSL https://git.rukavishnikoff.ru/hacker07/3X-UI_autoVPS/raw/tag/v1.2.3/scripts/3x-ui-local.sh) --domain vpn.example.com
# то же, но без защиты (--no-harden) и с добавлением второго порта SSH
bash <(curl -fsSL …/scripts/3x-ui-local.sh) --sni dl.google.com --no-harden --ssh-port 2222
# только установщик автора, без наших дополнений
bash <(curl -fsSL https://git.rukavishnikoff.ru/hacker07/3X-UI_autoVPS/raw/branch/main/scripts/3x-ui.sh)
# обновление уже стоящего сервера (тянет наш релиз и проверяет нашу подпись)
+1 -1
View File
@@ -1 +1 @@
1.2.2
1.2.3
+191
View File
@@ -0,0 +1,191 @@
#!/usr/bin/env bash
# 3X-UI KIT (форк hacker07) — установка сервера одной командой из нашего канала.
#
# Что делает (по шагам):
# 1) проверяет, что мы на чистом Debian/Ubuntu и под root, и что есть curl, ssh-keygen, openssl;
# 2) берёт из нашего Gitea релиз своей же версии, проверяет ПОДПИСЬ SHA256SUMS и SHA256 установщика;
# 3) запускает установщик автора (scripts/3x-ui.sh) — панель 3X-UI, протоколы, сайт-заглушка,
# маскировка, сертификат, подписка, ufw; все обычные флаги установщика можно передавать как есть;
# 4) досыпает то, чего у автора нет (поведение из StressOzz/vps-setup, но безопаснее):
# ответ на ping закрывается правилом ufw, включаются обновления безопасности;
# 5) при желании добавляет второй порт SSH (--ssh-port 2222) — прежний остаётся рабочим;
# 6) в конце: kit fix (время и безопасные починки), kit check, kit local hardening.
#
# Запуск (примеры):
# bash <(curl -fsSL https://git.rukavishnikoff.ru/hacker07/3X-UI_autoVPS/raw/tag/v1.2.3/scripts/3x-ui-local.sh) --domain vpn.example.com
# ... 3x-ui-local.sh --sni dl.google.com --harden
# ... 3x-ui-local.sh --ssh-port 2222 --no-harden
#
# Флаги самого обёрточного скрипта (остальные уходят установщику автора):
# --no-harden не отключать ping и не включать автообновления безопасности
# --ssh-port N добавить порт SSH N (прежний порт продолжает работать)
# --no-time не запускать kit fix (синхронизация времени и безопасные починки)
# --no-check не запускать в конце kit check
# --dry-run показать план и ничего не делать
# -h | --help эта справка
#
# Наш файл: авторские релизы его не перезаписывают, а правки форка живут в scripts/kit-local.sh.
set -Eeuo pipefail
KIT_VERSION="1.2.3" # версия сборки форка; должна совпадать с VERSION релиза
GITEA="${KIT_FORK_BASE:-https://git.rukavishnikoff.ru/hacker07/3X-UI_autoVPS}"
NS="3x-ui-kit-release"
SIG_ID="releases@3x-ui-kit"
# Публичный ключ форка. Меняется только вместе с ключом подписи (тогда обновляется и здесь, и в kit).
SIGNER_PUB='ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIKM0Sfn/UQeqjvUvY9wVgg7QtG1RR2pEUkqrUD5Yy6EF 3X-UI KIT fork releases (hacker07)'
G=$'\e[32m'; Y=$'\e[33m'; R=$'\e[31m'; B=$'\e[1m'; D=$'\e[2m'; N=$'\e[0m'
[[ -t 1 ]] || { G=; Y=; R=; B=; D=; N=; }
say() { printf '%s\n' "${G}==>${N} $*"; }
warn() { printf '%s\n' "${Y}!${N} $*" >&2; }
die() { printf '%s\n' "${R}✗${N} $*" >&2; exit 1; }
usage() {
cat <<'EOF'
3X-UI KIT (форк hacker07) — установка сервера одной командой из нашего канала.
bash <(curl -fsSL <наш Gitea>/raw/tag/v<версия>/scripts/3x-ui-local.sh) [флаги…]
Всё, что скрипт не знает сам, он передаёт установщику автора как есть:
--domain vpn.example.com свой домен для маскировки (A-запись на этот сервер, свободный 80)
--sni сайт.com маскировка под чужой сайт
--panel-on domain | ip где открывать панель и подписку
--host IP, --user имя, --port N, --protocols …, --restore файл
Флаги этого скрипта:
--no-harden не отключать ответ на ping и не включать автообновления безопасности
--ssh-port N добавить порт SSH N (прежний порт продолжает работать)
--no-time не запускать kit fix (время и безопасные починки)
--no-check не запускать в конце kit check
--dry-run показать план и ничего не делать
-h | --help эта справка
Что скрипт делает: проверяет сервер → скачивает релиз своей же версии из нашего Gitea,
проверяет подпись SHA256SUMS и SHA256 установщика → запускает установщик автора → досыпает
защиту (ping off правилом ufw, автообновления безопасности, при желании второй порт SSH) →
kit fix и kit check.
EOF
}
# ------------------------------------------------------------------ разбор флагов
INSTALLER_ARGS=(); harden=yes; ssh_port=""; fix_time=yes; do_check=yes; dry=no
while (($#)); do
case $1 in
--no-harden) harden=no ;;
--ssh-port) ssh_port=${2:-}; shift || die "--ssh-port: нужен номер порта" ;;
--ssh-port=*) ssh_port=${1#*=} ;;
--no-time) fix_time=no ;;
--no-check) do_check=no ;;
--dry-run) dry=yes ;;
-h | --help) usage; exit 0 ;;
*) INSTALLER_ARGS+=("$1") ;;
esac
shift
done
[[ -z $ssh_port || $ssh_port =~ ^[0-9]{1,5}$ ]] || die "--ssh-port: нужен номер порта, например 2222"
pre() { printf ' %s\n' "$*"; }
if [[ $dry == yes ]]; then
say "план установки (--dry-run: ничего не делаю)"
pre "версия сборки: $KIT_VERSION"
pre "откуда: $GITEA (тег v$KIT_VERSION), подпись проверяется ключом форка"
if ((${#INSTALLER_ARGS[@]})); then pre "установщик автора: bash scripts/3x-ui.sh ${INSTALLER_ARGS[*]}"; else pre "установщик автора: bash scripts/3x-ui.sh (без доп. флагов)"; fi
pre "маскировка: своя заглушка/домен — как решит установщик автора"
if [[ $harden == yes ]]; then pre "защита: ping off (правилом ufw) + автообновления безопасности"; else pre "защита: пропускаю (--no-harden)"; fi
[[ -n $ssh_port ]] && pre "порт SSH: добавляю $ssh_port (прежний остаётся рабочим)"
[[ $fix_time == yes ]] && pre "после: kit fix (время, безопасные починки)"
[[ $do_check == yes ]] && pre "проверка: kit check + kit local hardening"
echo
say "запуск без --dry-run выполнит всё это на сервере"
exit 0
fi
# ------------------------------------------------------------------ предполётные проверки
say "проверяю сервер"
[[ ${EUID:-0} -eq 0 ]] || die "нужен root: запустите от root (на чистом VPS обычно так и есть)"
[[ -r /etc/os-release ]] || die "не вижу /etc/os-release — это не Debian/Ubuntu?"
# shellcheck disable=SC1091
. /etc/os-release
case ${ID:-} in debian | ubuntu | raspbian) ;; *) warn "система ${PRETTY_NAME:-?}: поддерживаются Debian и Ubuntu" ;; esac
for c in curl ssh-keygen openssl; do command -v "$c" >/dev/null || die "нет $c — поставьте: apt-get update && apt-get install -y $c"; done
printf ' %s\n' "${PRETTY_NAME:-Linux}, ядро $(uname -r), памяти $(awk '/MemTotal/ {printf "%.1f ГБ", $2 / 1048576}' /proc/meminfo 2>/dev/null || echo '?')"
df -P / | awk 'NR==2 {gsub("%","",$5); if ($5 >= 95) exit 1}' || warn "диск занят почти полностью — установка может не пройти"
for p in 443 80; do ss -H -ltn 2>/dev/null | awk '{print $4}' | grep -qE "[:.]$p\$" && warn "порт $p уже кем-то занят"; done
# ------------------------------------------------------------------ релиз: скачать и проверить подпись
say "беру релиз v$KIT_VERSION и проверяю подпись"
tmp=$(mktemp -d)
trap 'rm -rf "$tmp"' EXIT
raw="$GITEA/raw/tag/v$KIT_VERSION"
for f in SHA256SUMS SHA256SUMS.sig scripts/3x-ui.sh; do
mkdir -p "$tmp/$(dirname "$f")"
curl -fsSL --retry 3 -m 60 -o "$tmp/$f" "$raw/$f" || die "не скачался $f из $raw (Gitea доступна с сервера?)"
done
printf '%s namespaces="%s" %s\n' "$SIG_ID" "$NS" "$SIGNER_PUB" >"$tmp/allowed_signers"
ssh-keygen -Y verify -f "$tmp/allowed_signers" -I "$SIG_ID" -n "$NS" -s "$tmp/SHA256SUMS.sig" <"$tmp/SHA256SUMS" >/dev/null 2>&1 \
|| die "подпись релиза v$KIT_VERSION не сошлась с ключом форка — это не наш релиз, ничего не запускаю"
sum=$(awk '$2 == "scripts/3x-ui.sh" {print $1}' "$tmp/SHA256SUMS")
[[ $(printf '%s' "$sum" | wc -c) -eq 64 ]] || die "в SHA256SUMS нет установщика — релиз собран неверно"
got=$(sha256sum "$tmp/scripts/3x-ui.sh" | awk '{print $1}')
[[ $got == "$sum" ]] || die "SHA256 установщика не совпал с подписанным — не запускаю"
bash -n "$tmp/scripts/3x-ui.sh" || die "установщик не проходит проверку синтаксиса"
printf ' ✓ подпись сошлась, SHA256 установщика совпал\n'
# ------------------------------------------------------------------ установка
say "запускаю установщик автора (панель 3X-UI, протоколы, сайт-заглушка, подписка)"
if ((${#INSTALLER_ARGS[@]})); then printf ' флаги: %s\n' "${INSTALLER_ARGS[*]}"; fi
# stdin: если есть терминал — отдаём его установщику (там есть вопросы), иначе /dev/null,
# иначе установщик начнёт читать наш собственный скрипт вместо ответов.
if [[ -t 0 ]] || { : </dev/tty; } 2>/dev/null; then
bash "$tmp/scripts/3x-ui.sh" ${INSTALLER_ARGS[@]+"${INSTALLER_ARGS[@]}"} </dev/tty || die "установщик остановился с ошибкой — он ничего не тронул дальше своего лога"
else
bash "$tmp/scripts/3x-ui.sh" ${INSTALLER_ARGS[@]+"${INSTALLER_ARGS[@]}"} </dev/null || die "установщик остановился с ошибкой (нет терминала — вопросы задать некому)"
fi
command -v kit >/dev/null || die "после установки нет команды kit — что-то пошло не так, смотрите вывод выше"
# ------------------------------------------------------------------ наши дополнения
if [[ $fix_time == yes ]]; then
say "kit fix: синхронизация времени и безопасные починки (авторская команда, ничего необратимого)"
kit fix || warn "kit fix завершился с замечаниями — посмотрите вывод"
fi
if [[ $harden == yes ]]; then
say "защита сервера: закрываю ответ на ping и включаю обновления безопасности"
kit local ping off || warn "не удалось закрыть ping — повторите: kit local ping off"
kit local upgrades on || warn "не удалось включить автообновления — повторите: kit local upgrades on"
fi
if [[ -n $ssh_port ]]; then
say "добавляю порт SSH $ssh_port (прежний порт продолжает работать)"
kit local ssh "$ssh_port" || warn "порт не добавился — сделайте это отдельно: kit local ssh $ssh_port"
cat <<EOF
${Y}Дальше обязательно:${N}
проверьте вход во ВТОРОМ окне: ssh -p $ssh_port root@<IP сервера>
убедились — закройте прежние порты: kit local ssh --close-old $ssh_port
EOF
fi
# ------------------------------------------------------------------ проверка
if [[ $do_check == yes ]]; then
say "проверяю, что получилось"
kit check || warn "kit check нашёл замечания — читайте выше; безопасные починки: kit fix"
kit local hardening
fi
cat <<EOF
${G}${B}Готово.${N} Сервер поставлен из нашей сборки (3X-UI KIT $KIT_VERSION, канал: наш Gitea).
подписка и ссылки: kit user link admin (или страница подписки из вывода установщика)
если что-то не так: kit check --deep, затем kit fix
вернуться к авторскому каналу: положить авторский kit поверх и выполнить kit update --force
EOF
+1 -1
View File
@@ -30,7 +30,7 @@ wait_apt_idle() {
XUI_VERSION="v3.9.0"
# SHA256 установщика 3X-UI этой версии: тег могут передвинуть, а хеш – нет (проверено 2026-09-30).
XUI_INSTALL_SHA256="18616fe26c8f6c92db6daa2dcd7cd53c5143ee69ecfd26d8ea6dc9b2c78607a6"
KIT_VERSION="1.2.2"
KIT_VERSION="1.2.3"
# kit и kit-sub берём из того же релиза, что и этот скрипт, а не из меняющейся ветки main.
KIT_RAW="https://git.rukavishnikoff.ru/hacker07/3X-UI_autoVPS/raw/tag/v$KIT_VERSION"
# Ядро Xray для панели. С 26.7.x клиенты на Mihomo и sing-box (Hiddify, FlClash,
+1 -1
View File
@@ -8,7 +8,7 @@
# Код выхода 1 при любом запуске (и при `__update_binary`) – старый `hy2 update` на нём
# останавливается и не заменяет команду hy2.
KIT_VERSION="1.2.2"
KIT_VERSION="1.2.3"
cat >&2 <<'MSG'
Отдельный установщик Hysteria2 больше не поддерживается.
+1 -1
View File
@@ -12,7 +12,7 @@
set -Eeuo pipefail
export LC_ALL=C.UTF-8 # ширина колонок по символам, а не байтам
KIT_VERSION="1.2.2"
KIT_VERSION="1.2.3"
KIT_RAW="https://git.rukavishnikoff.ru/hacker07/3X-UI_autoVPS/raw/branch/main"
# Файлы новой версии берём из её тега, а не из меняющейся ветки main.
kit_ref_raw() { echo "https://git.rukavishnikoff.ru/hacker07/3X-UI_autoVPS/raw/tag/v$1"; }
+1 -1
View File
@@ -169,7 +169,7 @@ def main():
"tools/release.sh",
"FILES=(scripts/3x-ui.sh scripts/hysteria2.sh scripts/kit.sh scripts/kit-sub.py VERSION)",
False,
"FILES=(scripts/3x-ui.sh scripts/hysteria2.sh scripts/kit.sh scripts/kit-sub.py scripts/kit-local.sh VERSION)",
"FILES=(scripts/3x-ui.sh scripts/hysteria2.sh scripts/kit.sh scripts/kit-sub.py scripts/kit-local.sh scripts/3x-ui-local.sh VERSION)",
"наш файл в подписанном списке релиза",
),
# --- свои записи о версии (наш файл, авторский CHANGELOG не трогаем) ----
+1 -1
View File
@@ -19,7 +19,7 @@ key=${1:-$HOME/.ssh/3xui_kit_release}
[[ -f $key ]] || die "Нет закрытого ключа $key. Создать: ssh-keygen -t ed25519 -C \"3X-UI KIT releases\" -f $key"
NS="3x-ui-kit-release"
ID="releases@3x-ui-kit"
FILES=(scripts/3x-ui.sh scripts/hysteria2.sh scripts/kit.sh scripts/kit-sub.py scripts/kit-local.sh VERSION)
FILES=(scripts/3x-ui.sh scripts/hysteria2.sh scripts/kit.sh scripts/kit-sub.py scripts/kit-local.sh scripts/3x-ui-local.sh VERSION)
v=$(tr -d '[:space:]' <VERSION)
[[ $v =~ ^[0-9]+(\.[0-9]+)+$ ]] || die "VERSION: $v"