From 1fdc4945f12db309f6e1e4ed540f97ff5a165374 Mon Sep 17 00:00:00 2001 From: hacker07 Date: Mon, 12 Oct 2026 20:25:02 +0300 Subject: [PATCH] =?UTF-8?q?v1.2.6:=20=D0=B2=D0=BE=D0=BF=D1=80=D0=BE=D1=81?= =?UTF-8?q?=20=D0=BF=D1=80=D0=BE=20=D1=81=D0=BC=D0=B5=D0=BD=D1=83=20=D0=BF?= =?UTF-8?q?=D0=BE=D1=80=D1=82=D0=B0=20SSH=20=D0=B2=D0=BC=D0=B5=D1=81=D1=82?= =?UTF-8?q?=D0=BE=20=D0=B2=D1=82=D0=BE=D1=80=D0=BE=D0=B3=D0=BE=20=D0=BF?= =?UTF-8?q?=D0=BE=D1=80=D1=82=D0=B0;=20=D0=BC=D0=B5=D0=BD=D1=8E=20=D0=B8?= =?UTF-8?q?=20=D0=B2=D0=BE=D0=BF=D1=80=D0=BE=D1=81=D1=8B=20=D0=B1=D0=BE?= =?UTF-8?q?=D0=BB=D1=8C=D1=88=D0=B5=20=D0=BD=D0=B5=20=D0=BF=D0=BE=D0=BF?= =?UTF-8?q?=D0=B0=D0=B4=D0=B0=D1=8E=D1=82=20=D0=B2=20=D0=B7=D0=BD=D0=B0?= =?UTF-8?q?=D1=87=D0=B5=D0=BD=D0=B8=D1=8F=20=D0=BF=D0=B5=D1=80=D0=B5=D0=BC?= =?UTF-8?q?=D0=B5=D0=BD=D0=BD=D1=8B=D1=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- FORK-CHANGELOG.md | 5 ++- FORK.md | 6 +-- scripts/3x-ui-local.sh | 87 ++++++++++++++++++++++++++---------------- 3 files changed, 61 insertions(+), 37 deletions(-) diff --git a/FORK-CHANGELOG.md b/FORK-CHANGELOG.md index 2263d7d..92d2914 100644 --- a/FORK-CHANGELOG.md +++ b/FORK-CHANGELOG.md @@ -11,8 +11,11 @@ (`ALL_PROTOS`/`DEFAULT_PROTOS`), передаётся его же флагом `--protocols`, так что поведение не расходится с авторским. Свой `--protocols` можно задать флагом — тогда вопроса не будет. * Обёртка `scripts/3x-ui-local.sh` теперь спрашивает, а не решает за вас: закрывать ли ответ на ping, - включать ли автообновления безопасности, добавлять ли второй порт SSH, менять ли пароль root. + включать ли автообновления безопасности, **менять ли порт SSH** (Enter — оставить текущий, + число — перевести на него; мусор и занятый порт переспрашивает), менять ли пароль root. Маскировку и домен, как и раньше, спрашивает установщик автора. +* Смена порта SSH никогда не закрывает прежний порт сама: сначала добавляется новый, затем скрипт + печатает две команды — проверить вход во втором окне и закрыть прежние (`kit local ssh --close-old`). * Запуск без флагов = «одна команда, дальше вопросы». Флаг `--yes` — наоборот, ничего не спрашивать (для автоматизации): ping закрывается, автообновления включаются, порт SSH и пароль не трогаются. * Флаг `--harden` теперь действительно существует (раньше он уходил установщику автора неизвестным diff --git a/FORK.md b/FORK.md index 7cc46d0..06075f4 100644 --- a/FORK.md +++ b/FORK.md @@ -10,8 +10,8 @@ порт 80 (иначе Let's Encrypt не выпустит сертификат). Без домена этот шаг пропускается. 2. Одна команда на сервере (от root) — **дальше скрипт спросит сам**: какие протоколы ставить (нумерованный список: `1,3,11` или «все», Enter — набор автора), какую маскировку и домен, - закрывать ли ответ на ping, включать ли автообновления, добавлять ли второй порт SSH, - менять ли пароль root: + закрывать ли ответ на ping, включать ли автообновления, менять ли порт SSH (Enter — оставить + текущий, число — перевести на него), менять ли пароль root: ```bash bash <(curl -fsSL https://git.rukavishnikoff.ru/hacker07/3X-UI_autoVPS/raw/branch/main/scripts/3x-ui-local.sh) @@ -47,7 +47,7 @@ bash <(curl -fsSL …/scripts/3x-ui-local.sh) --dry-run --domain vpn.example.com | `--domain домен` | свой домен для маскировки: сайт и REALITY маскируются под него (A-запись на сервер, свободный 80) | | `--sni сайт.com` | маскировка под чужой сайт вместо домена | | `--panel-on domain\|ip` | где открывать панель и подписку | -| `--ssh-port N` | добавить второй порт SSH (прежний продолжает работать; закрытие — отдельным шагом) | +| `--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` | проверить релиз / показать план и ничего не менять | diff --git a/scripts/3x-ui-local.sh b/scripts/3x-ui-local.sh index fe431c2..edb8946 100644 --- a/scripts/3x-ui-local.sh +++ b/scripts/3x-ui-local.sh @@ -10,7 +10,7 @@ # 4) спрашивает, какие протоколы ставить: невыбранные не создаются вообще — ни подключения в панели, # ни записей в nginx, ни ссылок в подписке (за это отвечает флаг автора --protocols); # 5) спрашивает и делает то, чего у автора нет: закрыть ответ на ping, включить обновления -# безопасности, добавить второй порт SSH, сменить пароль root (поведение из StressOzz/vps-setup, +# безопасности, перевести SSH на другой порт, сменить пароль root (поведение из StressOzz/vps-setup, # но безопаснее); # 6) в конце: kit fix (время и безопасные починки), kit check, kit local hardening. # @@ -71,7 +71,7 @@ usage() { Флаги этого скрипта: --harden закрыть ping и включить автообновления, без вопросов --no-harden не трогать ping и автообновления - --ssh-port N добавить порт SSH N (прежний порт продолжает работать) + --ssh-port N перевести SSH на порт N (прежний закроется после проверки входа) --yes ни о чём не спрашивать (для автоматизации) --no-time не запускать kit fix (время и безопасные починки) --no-check не запускать в конце kit check @@ -100,7 +100,8 @@ while (($#)); do esac shift done -[[ -z $ssh_port || $ssh_port =~ ^[0-9]{1,5}$ ]] || die "--ssh-port: нужен номер порта, например 2222" +[[ -z $ssh_port ]] || { [[ $ssh_port =~ ^[0-9]{1,5}$ ]] && ((10#$ssh_port >= 1024 && 10#$ssh_port <= 65535)); } \ + || die "--ssh-port: нужно число 1024–65535, например 2222" # Если --protocols задан флагом — не спрашиваем и не дублируем его. proto_flag="" @@ -125,8 +126,8 @@ if [[ $dry == yes ]]; then if [[ -n $proto_flag ]]; then pre "протоколы: ${proto_flag} (задано флагом)" elif interactive; then pre "протоколы: спрошу (Enter — всё, кроме WireGuard и REALITY-2)" else pre "протоколы: всё, кроме WireGuard и REALITY-2"; fi - if [[ -n $ssh_port ]]; then pre "порт SSH: добавляю $ssh_port (прежний остаётся рабочим)" - elif interactive; then pre "порт SSH: спрошу (Enter — не менять)"; fi + if [[ -n $ssh_port ]]; then pre "порт SSH: перевожу на $ssh_port (прежний — после проверки входа)" + elif interactive; then pre "порт SSH: спрошу (Enter — оставить текущий)"; fi if interactive; then pre "пароль root: спрошу (по умолчанию — не менять)"; fi [[ $fix_time == yes ]] && pre "после: kit fix (время, безопасные починки)" [[ $do_check == yes ]] && pre "проверка: kit check + kit local hardening" @@ -200,13 +201,13 @@ DEFAULT_PROTOS=(reality hy2 xhttp ws trojan vmess ss tuic awg awg3 mtproto) proto_menu() { local i n mark - say "какие протоколы поставить?" + say "какие протоколы поставить?" >&2 for i in "${!ALL_PROTOS[@]}"; do n=$((i + 1)) mark=" " [[ " ${DEFAULT_PROTOS[*]} " == *" ${ALL_PROTOS[i]} "* ]] && mark="*" - printf ' %s %2d. %s\n' "$mark" "$n" "${PROTO_HINT[i]}" + printf ' %s %2d. %s\n' "$mark" "$n" "${PROTO_HINT[i]}" >&2 done - printf ' %s\n' "${D}[* — набор по умолчанию (всё, кроме WireGuard и REALITY-2). Невыбранные протоколы не создаются вообще.]${N}" + printf ' %s\n' "${D}[* — набор по умолчанию (всё, кроме WireGuard и REALITY-2). Невыбранные протоколы не создаются вообще.]${N}" >&2 } proto_parse() { # ответ → выбранные имена через запятую; код 1, если не разобрал @@ -237,7 +238,7 @@ ask_protocols() { # печатает итоговый список через з interactive || { printf '%s' "$(IFS=,; echo "${DEFAULT_PROTOS[*]}")"; return 0; } proto_menu for i in 1 2 3; do - printf '\n%sНомера через запятую (например 1,3,11) или «все»; Enter — набор по умолчанию: %s' "$B" "$N" + printf '\n%sНомера через запятую (например 1,3,11) или «все»; Enter — набор по умолчанию: %s' "$B" "$N" >&2 ans="" read -r -t 300 ans <"$ASK_SRC" 2>/dev/null || true if picked=$(proto_parse "$ans"); then printf '%s' "$picked"; return 0; fi @@ -280,14 +281,6 @@ ask_yes() { # "вопрос" y|n — по умолчанию [[ $ans =~ ^(y|yes|д|да)$ ]] } -ask_value() { # "вопрос" → ответ (пусто, если терминала нет или ответа нет) - interactive || return 0 - printf '\n%s: ' "$1" - local v="" - read -r -t 300 v <"$ASK_SRC" 2>/dev/null || true - printf '%s' "${v//[[:space:]]/}" -} - if [[ $fix_time == yes ]]; then say "kit fix: синхронизация времени и безопасные починки (авторская команда, ничего необратимого)" kit fix || warn "kit fix завершился с замечаниями — посмотрите вывод" @@ -310,24 +303,52 @@ if [[ $want_update == yes ]]; then kit local upgrades on || warn "не удалось — повторите: kit local upgrades on" fi -# второй порт SSH: по флагу, иначе по вопросу -if [[ -z $ssh_port ]] && interactive; then - answer=$(ask_value "Добавить второй порт для SSH? Введите номер, например 2222 (Enter — не менять)") - [[ -n $answer ]] && ssh_port=$answer -fi -if [[ -n $ssh_port ]]; then - if [[ $ssh_port =~ ^[0-9]{1,5}$ ]]; then - say "добавляю порт SSH $ssh_port (прежний порт продолжает работать)" - kit local ssh "$ssh_port" || warn "порт не добавился — сделайте отдельно: kit local ssh $ssh_port" - cat </dev/null | sed -n 's/^порты SSH сейчас: //p') + [[ -n $p ]] || p=$(sshd -T 2>/dev/null | awk '$1 == "port" {print $2}' | paste -sd, -) + [[ -n $p ]] || p=$(grep -rhiE '^[[:space:]]*Port[[:space:]]+[0-9]+' /etc/ssh/sshd_config /etc/ssh/sshd_config.d 2>/dev/null | awk '{print $2}' | paste -sd, -) + printf '%s' "${p:-22}" +} - ${Y}Дальше обязательно:${N} - проверьте вход во ВТОРОМ окне: ssh -p $ssh_port root@ - убедились — закройте прежние порты: kit local ssh --close-old $ssh_port +ask_ssh_port() { # пусто — оставить как есть; иначе номер нового порта + local cur ans try + cur=$(ssh_ports_now) + interactive || return 0 + for try in 1 2 3; do + printf '\n%sСменить порт SSH? Сейчас %s. Введите новый номер, Enter — оставить как есть: %s' "$B" "$cur" "$N" >&2 + ans="" + read -r -t 300 ans <"$ASK_SRC" 2>/dev/null || true + ans=${ans//[[:space:]]/} + [[ -n $ans ]] || { say "порт SSH оставляю как есть ($cur)" >&2; return 0; } + if ! [[ $ans =~ ^[0-9]{1,5}$ ]] || ((10#$ans < 1024 || 10#$ans > 65535)); then + warn "«$ans» не похоже на порт (нужно число 1024–65535)" + continue + fi + if [[ ,$cur, == *",$ans,"* ]]; then + say "порт $ans уже слушает SSH — менять нечего" >&2; return 0 + fi + if ss -H -ltn 2>/dev/null | awk '{print $4}' | grep -qE "[:.]$ans\$"; then + warn "порт $ans/tcp занят другой программой" + continue + fi + printf '%s' "$ans"; return 0 + done + warn "оставляю прежний порт ($cur)" +} + +[[ -n $ssh_port ]] || ssh_port=$(ask_ssh_port) +if [[ -n $ssh_port ]]; then + say "перевожу SSH на порт $ssh_port: новый добавляю, прежний пока остаётся рабочим" + kit local ssh "$ssh_port" || warn "порт не добавился — сделайте отдельно: kit local ssh $ssh_port" + cat < + 2) вход работает — закройте прежние порты: kit local ssh --close-old $ssh_port EOF - else - warn "«$ssh_port» не похоже на номер порта — пропускаю (позже: kit local ssh 2222)" - fi fi # пароль root: в флагах его нет намеренно — значение в командной строке видно в списке процессов