v1.2.6: вопрос про смену порта SSH вместо второго порта; меню и вопросы больше не попадают в значения переменных

This commit is contained in:
2026-10-12 20:25:15 +03:00
parent cc17b11bd1
commit 1fdc4945f1
3 changed files with 61 additions and 37 deletions
+4 -1
View File
@@ -11,8 +11,11 @@
(`ALL_PROTOS`/`DEFAULT_PROTOS`), передаётся его же флагом `--protocols`, так что поведение (`ALL_PROTOS`/`DEFAULT_PROTOS`), передаётся его же флагом `--protocols`, так что поведение
не расходится с авторским. Свой `--protocols` можно задать флагом — тогда вопроса не будет. не расходится с авторским. Свой `--protocols` можно задать флагом — тогда вопроса не будет.
* Обёртка `scripts/3x-ui-local.sh` теперь спрашивает, а не решает за вас: закрывать ли ответ на ping, * Обёртка `scripts/3x-ui-local.sh` теперь спрашивает, а не решает за вас: закрывать ли ответ на ping,
включать ли автообновления безопасности, добавлять ли второй порт SSH, менять ли пароль root. включать ли автообновления безопасности, **менять ли порт SSH** (Enter — оставить текущий,
число — перевести на него; мусор и занятый порт переспрашивает), менять ли пароль root.
Маскировку и домен, как и раньше, спрашивает установщик автора. Маскировку и домен, как и раньше, спрашивает установщик автора.
* Смена порта SSH никогда не закрывает прежний порт сама: сначала добавляется новый, затем скрипт
печатает две команды — проверить вход во втором окне и закрыть прежние (`kit local ssh --close-old`).
* Запуск без флагов = «одна команда, дальше вопросы». Флаг `--yes` — наоборот, ничего не спрашивать * Запуск без флагов = «одна команда, дальше вопросы». Флаг `--yes` — наоборот, ничего не спрашивать
(для автоматизации): ping закрывается, автообновления включаются, порт SSH и пароль не трогаются. (для автоматизации): ping закрывается, автообновления включаются, порт SSH и пароль не трогаются.
* Флаг `--harden` теперь действительно существует (раньше он уходил установщику автора неизвестным * Флаг `--harden` теперь действительно существует (раньше он уходил установщику автора неизвестным
+3 -3
View File
@@ -10,8 +10,8 @@
порт 80 (иначе Let's Encrypt не выпустит сертификат). Без домена этот шаг пропускается. порт 80 (иначе Let's Encrypt не выпустит сертификат). Без домена этот шаг пропускается.
2. Одна команда на сервере (от root) — **дальше скрипт спросит сам**: какие протоколы ставить 2. Одна команда на сервере (от root) — **дальше скрипт спросит сам**: какие протоколы ставить
(нумерованный список: `1,3,11` или «все», Enter — набор автора), какую маскировку и домен, (нумерованный список: `1,3,11` или «все», Enter — набор автора), какую маскировку и домен,
закрывать ли ответ на ping, включать ли автообновления, добавлять ли второй порт SSH, закрывать ли ответ на ping, включать ли автообновления, менять ли порт SSH (Enter — оставить
менять ли пароль root: текущий, число — перевести на него), менять ли пароль root:
```bash ```bash
bash <(curl -fsSL https://git.rukavishnikoff.ru/hacker07/3X-UI_autoVPS/raw/branch/main/scripts/3x-ui-local.sh) 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) | | `--domain домен` | свой домен для маскировки: сайт и REALITY маскируются под него (A-запись на сервер, свободный 80) |
| `--sni сайт.com` | маскировка под чужой сайт вместо домена | | `--sni сайт.com` | маскировка под чужой сайт вместо домена |
| `--panel-on domain\|ip` | где открывать панель и подписку | | `--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-harden` | не закрывать ответ на ping и не включать автообновления безопасности |
| `--no-time` / `--no-check` | не запускать `kit fix` / `kit check` | | `--no-time` / `--no-check` | не запускать `kit fix` / `kit check` |
| `--verify-only` / `--dry-run` | проверить релиз / показать план и ничего не менять | | `--verify-only` / `--dry-run` | проверить релиз / показать план и ничего не менять |
+51 -30
View File
@@ -10,7 +10,7 @@
# 4) спрашивает, какие протоколы ставить: невыбранные не создаются вообще — ни подключения в панели, # 4) спрашивает, какие протоколы ставить: невыбранные не создаются вообще — ни подключения в панели,
# ни записей в nginx, ни ссылок в подписке (за это отвечает флаг автора --protocols); # ни записей в nginx, ни ссылок в подписке (за это отвечает флаг автора --protocols);
# 5) спрашивает и делает то, чего у автора нет: закрыть ответ на ping, включить обновления # 5) спрашивает и делает то, чего у автора нет: закрыть ответ на ping, включить обновления
# безопасности, добавить второй порт SSH, сменить пароль root (поведение из StressOzz/vps-setup, # безопасности, перевести SSH на другой порт, сменить пароль root (поведение из StressOzz/vps-setup,
# но безопаснее); # но безопаснее);
# 6) в конце: kit fix (время и безопасные починки), kit check, kit local hardening. # 6) в конце: kit fix (время и безопасные починки), kit check, kit local hardening.
# #
@@ -71,7 +71,7 @@ usage() {
Флаги этого скрипта: Флаги этого скрипта:
--harden закрыть ping и включить автообновления, без вопросов --harden закрыть ping и включить автообновления, без вопросов
--no-harden не трогать ping и автообновления --no-harden не трогать ping и автообновления
--ssh-port N добавить порт SSH N (прежний порт продолжает работать) --ssh-port N перевести SSH на порт N (прежний закроется после проверки входа)
--yes ни о чём не спрашивать (для автоматизации) --yes ни о чём не спрашивать (для автоматизации)
--no-time не запускать kit fix (время и безопасные починки) --no-time не запускать kit fix (время и безопасные починки)
--no-check не запускать в конце kit check --no-check не запускать в конце kit check
@@ -100,7 +100,8 @@ while (($#)); do
esac esac
shift shift
done 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 задан флагом — не спрашиваем и не дублируем его. # Если --protocols задан флагом — не спрашиваем и не дублируем его.
proto_flag="" proto_flag=""
@@ -125,8 +126,8 @@ if [[ $dry == yes ]]; then
if [[ -n $proto_flag ]]; then pre "протоколы: ${proto_flag} (задано флагом)" if [[ -n $proto_flag ]]; then pre "протоколы: ${proto_flag} (задано флагом)"
elif interactive; then pre "протоколы: спрошу (Enter — всё, кроме WireGuard и REALITY-2)" elif interactive; then pre "протоколы: спрошу (Enter — всё, кроме WireGuard и REALITY-2)"
else pre "протоколы: всё, кроме WireGuard и REALITY-2"; fi else pre "протоколы: всё, кроме WireGuard и REALITY-2"; fi
if [[ -n $ssh_port ]]; then pre "порт SSH: добавляю $ssh_port (прежний остаётся рабочим)" if [[ -n $ssh_port ]]; then pre "порт SSH: перевожу на $ssh_port (прежний — после проверки входа)"
elif interactive; then pre "порт SSH: спрошу (Enter — не менять)"; fi elif interactive; then pre "порт SSH: спрошу (Enter — оставить текущий)"; fi
if interactive; then pre "пароль root: спрошу (по умолчанию — не менять)"; fi if interactive; then pre "пароль root: спрошу (по умолчанию — не менять)"; fi
[[ $fix_time == yes ]] && pre "после: kit fix (время, безопасные починки)" [[ $fix_time == yes ]] && pre "после: kit fix (время, безопасные починки)"
[[ $do_check == yes ]] && pre "проверка: kit check + kit local hardening" [[ $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() { proto_menu() {
local i n mark local i n mark
say "какие протоколы поставить?" say "какие протоколы поставить?" >&2
for i in "${!ALL_PROTOS[@]}"; do for i in "${!ALL_PROTOS[@]}"; do
n=$((i + 1)) mark=" " n=$((i + 1)) mark=" "
[[ " ${DEFAULT_PROTOS[*]} " == *" ${ALL_PROTOS[i]} "* ]] && 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 done
printf ' %s\n' "${D}[* — набор по умолчанию (всё, кроме WireGuard и REALITY-2). Невыбранные протоколы не создаются вообще.]${N}" printf ' %s\n' "${D}[* — набор по умолчанию (всё, кроме WireGuard и REALITY-2). Невыбранные протоколы не создаются вообще.]${N}" >&2
} }
proto_parse() { # ответ → выбранные имена через запятую; код 1, если не разобрал proto_parse() { # ответ → выбранные имена через запятую; код 1, если не разобрал
@@ -237,7 +238,7 @@ ask_protocols() { # печатает итоговый список через з
interactive || { printf '%s' "$(IFS=,; echo "${DEFAULT_PROTOS[*]}")"; return 0; } interactive || { printf '%s' "$(IFS=,; echo "${DEFAULT_PROTOS[*]}")"; return 0; }
proto_menu proto_menu
for i in 1 2 3; do 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="" ans=""
read -r -t 300 ans <"$ASK_SRC" 2>/dev/null || true read -r -t 300 ans <"$ASK_SRC" 2>/dev/null || true
if picked=$(proto_parse "$ans"); then printf '%s' "$picked"; return 0; fi if picked=$(proto_parse "$ans"); then printf '%s' "$picked"; return 0; fi
@@ -280,14 +281,6 @@ ask_yes() { # "вопрос" y|n — по умолчанию
[[ $ans =~ ^(y|yes|д|да)$ ]] [[ $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 if [[ $fix_time == yes ]]; then
say "kit fix: синхронизация времени и безопасные починки (авторская команда, ничего необратимого)" say "kit fix: синхронизация времени и безопасные починки (авторская команда, ничего необратимого)"
kit fix || warn "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" kit local upgrades on || warn "не удалось — повторите: kit local upgrades on"
fi fi
# второй порт SSH: по флагу, иначе по вопросу # порт SSH: по флагу или по вопросу. Смена делается в два шага: сначала ДОБАВИТЬ новый порт
if [[ -z $ssh_port ]] && interactive; then # (прежний продолжает работать), потом закрыть прежние — иначе одна опечатка оставляет сервер без доступа.
answer=$(ask_value "Добавить второй порт для SSH? Введите номер, например 2222 (Enter — не менять)") ssh_ports_now() {
[[ -n $answer ]] && ssh_port=$answer local p
fi p=$(kit local ssh --status 2>/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}"
}
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 if [[ -n $ssh_port ]]; then
if [[ $ssh_port =~ ^[0-9]{1,5}$ ]]; then say "перевожу SSH на порт $ssh_port: новый добавляю, прежний пока остаётся рабочим"
say "добавляю порт SSH $ssh_port (прежний порт продолжает работать)"
kit local ssh "$ssh_port" || warn "порт не добавился — сделайте отдельно: kit local ssh $ssh_port" kit local ssh "$ssh_port" || warn "порт не добавился — сделайте отдельно: kit local ssh $ssh_port"
cat <<EOF cat <<EOF
${Y}Дальше обязательно:${N} ${Y}Дальше обязательно (иначе можно потерять доступ к серверу):${N}
проверьте вход во ВТОРОМ окне: ssh -p $ssh_port root@<IP сервера> 1) откройте ВТОРОЕ окно и проверьте вход: ssh -p $ssh_port root@<IP сервера>
убедились — закройте прежние порты: kit local ssh --close-old $ssh_port 2) вход работает — закройте прежние порты: kit local ssh --close-old $ssh_port
EOF EOF
else
warn "«$ssh_port» не похоже на номер порта — пропускаю (позже: kit local ssh 2222)"
fi
fi fi
# пароль root: в флагах его нет намеренно — значение в командной строке видно в списке процессов # пароль root: в флагах его нет намеренно — значение в командной строке видно в списке процессов