diff --git a/CHANGELOG.md b/CHANGELOG.md index 44f1e1c..d033214 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,6 +22,7 @@ phobos-update beta # или: phobos-update dev ## stable ### v1.2.8 +- **fix:** install/update теперь запускают `phobos-self-check --fix`: автоматически чинят потерянный `=` в `SERVER_WG_PUBLIC_KEY`, сверяют ключ с `wg0`, проверяют router helper-файлы и shell syntax до выдачи клиентских ссылок. - **fix:** Android/iOS phone configs теперь восстанавливают потерянный `=` в WireGuard `PrivateKey/PublicKey/PresharedKey`. Это закрывает ошибку PhobosWG «Неправильная длина ключа в PublicKey». - **fix:** `lib-core.sh` больше не теряет финальный `=` при чтении `server.env`, поэтому новые клиентские `.conf` получают полный `PublicKey`. - **fix:** Android PhobosWG больше не получает `PresharedKey = none` в phobos payload, из-за чего импорт мог падать с «Неправильная длина ключа в PublicKey». @@ -60,6 +61,7 @@ phobos-update beta # или: phobos-update dev | 1.2.7 / 1.3.x | PhobosWG: «невозможно импортировать туннель» | `phobos://` дополняется `= none` для всех обязательных полей (`PresharedKey`) по спеке формата | | 1.2.8 / 1.3.x | Stable не показывал кнопку скачивания APK без локального файла | кнопка **PhobosWG (APK)** всегда доступна на Android-странице; `/download/apk` ведет на public stable release | | 1.2.8 / 1.3.x | Android PhobosWG: «Неправильная длина ключа в PublicKey» | Android/iOS payload восстанавливает потерянный `=` в WireGuard ключах и не добавляет `PresharedKey = none`; QR/link нужно открыть заново | +| 1.2.8 / 1.3.x | Установка/обновление могли пройти, но потом панель генерила кривую ссылку | `phobos-self-check --fix` встроен в install/update и доступен как отдельная команда | | 1.2.8 / 1.3.x | Router init: `can't open './lib-client.sh'` | обязательные router helper-скрипты добавлены в PCA overlay и managed update | | 1.2.8 / 1.3.x | Stable `/clients`: `lib-core.sh: No such file or directory`, `check_root/load_env: command not found` | `lib-core.sh` добавлен в public repo, installer и updater | | 1.2.8 / 1.3.x | Install `[6/9] PCA patches`: `curl: (23) Failure writing output to destination` | `fetch()` создаёт папку назначения перед `curl -o` | diff --git a/docs/TROUBLESHOOTING.md b/docs/TROUBLESHOOTING.md index ed01aa1..91d8ad0 100644 --- a/docs/TROUBLESHOOTING.md +++ b/docs/TROUBLESHOOTING.md @@ -140,6 +140,7 @@ test -f /opt/Phobos/repo/server/scripts/lib-core.sh && echo LIB_CORE_OK ```bash phobos-update stable +phobos-self-check --fix systemctl restart phobos-panel ``` @@ -571,6 +572,8 @@ systemctl restart phobos-panel 3. Сканируй новый QR или копируй новую `phobos://` ссылку. 4. Если клиент был создан старой версией и ошибка осталась, создай нового клиента именно для телефона. +В новых версиях `install.sh` и `phobos-update` запускают `phobos-self-check --fix` сами. Команда нужна только если хочешь повторно прогнать проверку на уже установленном сервере. + ### Android импорт прошел, но интернета нет В `[Peer]` должны быть маршруты: diff --git a/install.sh b/install.sh index bb33afa..4b604a6 100755 --- a/install.sh +++ b/install.sh @@ -215,11 +215,13 @@ fetch overlay/phobos-pull.sh "$PHOBOS_DIR/repo/client/templat fetch overlay/phobos-uninstall.sh "$PHOBOS_DIR/repo/client/templates/phobos-uninstall.sh" && chmod +x "$PHOBOS_DIR/repo/client/templates/phobos-uninstall.sh" fetch overlay/3xui.sh "$PHOBOS_DIR/repo/client/templates/3xui.sh" && chmod +x "$PHOBOS_DIR/repo/client/templates/3xui.sh" fetch server/phobos-health.sh "$PHOBOS_DIR/server/phobos-health.sh" && chmod +x "$PHOBOS_DIR/server/phobos-health.sh" +fetch server/phobos-self-check.sh "$PHOBOS_DIR/server/phobos-self-check.sh" && chmod +x "$PHOBOS_DIR/server/phobos-self-check.sh" && ln -sf "$PHOBOS_DIR/server/phobos-self-check.sh" /usr/local/bin/phobos-self-check fetch server/phobos-pull.sh "$PHOBOS_DIR/server/phobos-pull.sh" && chmod +x "$PHOBOS_DIR/server/phobos-pull.sh" fetch server/phobos-router-watchdog.py "$PHOBOS_DIR/server/phobos-router-watchdog.py" fetch update.sh "$PHOBOS_DIR/server/update.sh" && chmod +x "$PHOBOS_DIR/server/update.sh" && ln -sf "$PHOBOS_DIR/server/update.sh" /usr/local/bin/phobos-update mkdir -p "$PANEL_DIR"; fetch VERSION "$PANEL_DIR/.version" 2>/dev/null || true [ -f "$PHOBOS_DIR/tokens/tokens.json" ] || echo '[]' > "$PHOBOS_DIR/tokens/tokens.json" +"$PHOBOS_DIR/server/phobos-self-check.sh" --fix # ── 7. web panel ── echo "[7/9] web panel..." diff --git a/server/phobos-self-check.sh b/server/phobos-self-check.sh new file mode 100644 index 0000000..62c7b7d --- /dev/null +++ b/server/phobos-self-check.sh @@ -0,0 +1,117 @@ +#!/usr/bin/env bash +set -euo pipefail + +PHOBOS_DIR="${PHOBOS_DIR:-/opt/Phobos}" +SERVER_ENV="${SERVER_ENV:-$PHOBOS_DIR/server/server.env}" +REPO_DIR="${REPO_DIR:-$PHOBOS_DIR/repo}" +WG_IFACE="${WG_IFACE:-wg0}" +FIX=0 + +for arg in "$@"; do + [ "$arg" = "--fix" ] && FIX=1 +done + +log() { echo "[self-check] $*"; } +fail() { echo "[self-check][ERROR] $*" >&2; exit 1; } +warn() { echo "[self-check][WARN] $*" >&2; } + +env_get() { + local key="$1" + [ -f "$SERVER_ENV" ] || return 0 + while IFS= read -r line || [ -n "$line" ]; do + case "$line" in + "$key="*) printf '%s\n' "${line#*=}"; return 0 ;; + esac + done < "$SERVER_ENV" +} + +env_set() { + local key="$1" value="$2" tmp + [ -f "$SERVER_ENV" ] || fail "server.env не найден: $SERVER_ENV" + tmp="$(mktemp)" + awk -v k="$key" -v v="$value" ' + BEGIN { done=0 } + $0 ~ "^" k "=" { print k "=" v; done=1; next } + { print } + END { if (!done) print k "=" v } + ' "$SERVER_ENV" > "$tmp" + cat "$tmp" > "$SERVER_ENV" + rm -f "$tmp" + chmod 600 "$SERVER_ENV" 2>/dev/null || true +} + +normalize_wg_key() { + python3 - "$1" <<'PY' +import sys +value = (sys.argv[1] or "").strip() +alphabet = set("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=") +if value and value.lower() != "none" and all(ch in alphabet for ch in value): + padded = value + ("=" * ((4 - len(value) % 4) % 4)) + if len(padded) == 44: + value = padded +print(value) +PY +} + +check_env_key() { + local key="$1" value normalized + value="$(env_get "$key" || true)" + [ -n "$value" ] || fail "$key пустой или отсутствует в server.env" + normalized="$(normalize_wg_key "$value")" + if [ "$normalized" != "$value" ]; then + if [ "$FIX" = 1 ]; then + env_set "$key" "$normalized" + log "$key: восстановлен base64 padding" + value="$normalized" + else + fail "$key имеет длину ${#value}, нужен padding. Запусти phobos-self-check --fix" + fi + fi + [ "${#value}" = 44 ] || fail "$key имеет длину ${#value}, ожидается 44" +} + +check_public_key_matches_wg() { + local env_pub wg_pub + env_pub="$(env_get SERVER_WG_PUBLIC_KEY || true)" + wg_pub="$(wg show "$WG_IFACE" public-key 2>/dev/null || true)" + [ -n "$wg_pub" ] || return 0 + if [ "$env_pub" != "$wg_pub" ]; then + if [ "$FIX" = 1 ]; then + env_set SERVER_WG_PUBLIC_KEY "$wg_pub" + log "SERVER_WG_PUBLIC_KEY: обновлен из wg show $WG_IFACE" + else + fail "SERVER_WG_PUBLIC_KEY не совпадает с wg show $WG_IFACE" + fi + fi +} + +check_router_templates() { + local tpl="$REPO_DIR/client/templates" missing=0 file + for file in install-router.sh.template lib-client.sh install-obfuscator.sh install-wireguard.sh; do + if [ ! -s "$tpl/$file" ]; then + warn "нет обязательного router helper: $tpl/$file" + missing=1 + fi + done + [ "$missing" = 0 ] || fail "router package будет битый. Выполни phobos-update stable|beta|dev" +} + +check_scripts_syntax() { + local script + for script in \ + "$REPO_DIR/server/scripts/lib-core.sh" \ + "$REPO_DIR/server/scripts/phobos-client.sh" \ + "$REPO_DIR/client/templates/install-router.sh.template" \ + "$REPO_DIR/client/templates/lib-client.sh" \ + "$REPO_DIR/client/templates/install-obfuscator.sh" \ + "$REPO_DIR/client/templates/install-wireguard.sh"; do + [ -f "$script" ] && bash -n "$script" + done +} + +[ -f "$SERVER_ENV" ] || fail "server.env не найден: $SERVER_ENV" +check_env_key SERVER_WG_PUBLIC_KEY +check_public_key_matches_wg +check_router_templates +check_scripts_syntax +log "OK" diff --git a/update.sh b/update.sh index d009143..b6243f3 100755 --- a/update.sh +++ b/update.sh @@ -59,12 +59,22 @@ $PHOBOS_DIR/repo/client/templates/phobos-pull.sh|overlay/phobos-pull.sh $PHOBOS_DIR/repo/client/templates/phobos-uninstall.sh|overlay/phobos-uninstall.sh $PHOBOS_DIR/repo/client/templates/3xui.sh|overlay/3xui.sh $PHOBOS_DIR/server/phobos-health.sh|server/phobos-health.sh +$PHOBOS_DIR/server/phobos-self-check.sh|server/phobos-self-check.sh $PHOBOS_DIR/server/phobos-pull.sh|server/phobos-pull.sh $PHOBOS_DIR/server/phobos-router-watchdog.py|server/phobos-router-watchdog.py $PHOBOS_DIR/server/update.sh|update.sh LIST } +run_self_check() { + if [ -x "$PHOBOS_DIR/server/phobos-self-check.sh" ]; then + ln -sf "$PHOBOS_DIR/server/phobos-self-check.sh" /usr/local/bin/phobos-self-check 2>/dev/null || true + "$PHOBOS_DIR/server/phobos-self-check.sh" --fix + else + echo " WARN: phobos-self-check.sh не найден" + fi +} + # fetch VERSION of a channel (public repos / or private if token present) chan_version() { # $1 = ref(channel) local repo; repo=$(repo_for "$1"); local repo_ref="$1" @@ -139,6 +149,7 @@ case "${1:-}" in [ -f "$last/$rp" ] && { mkdir -p "$(dirname "$lp")"; cp "$last/$rp" "$lp"; chmod +x "$lp" 2>/dev/null || true; } done echo "$fromver" > "$VERFILE" + run_self_check systemctl restart phobos-panel 2>/dev/null || true echo "Откат выполнен -> $fromver" ;; @@ -167,6 +178,7 @@ case "${1:-}" in echo "Текущая: $CUR -> целевая: $target ($ref)" b=$(do_backup); echo "Бэкап: $b" apply_ref "$ref" + run_self_check echo "$target" > "$VERFILE" systemctl restart phobos-panel 2>/dev/null || true echo "Обновлено до $target. Откат: phobos-update --rollback"