Ground-Zerro / Phobos Public
Code Issues Pull requests Actions Releases View on GitHub ↗
23.9 KB plaintext
#!/bin/sh
set -e

CLIENT_NAME="{{CLIENT_NAME}}"
PHOBOS_DIR=""
ROUTER_PLATFORM=""

. "$(dirname "$0")/lib-client.sh"
. "$(dirname "$0")/install-obfuscator.sh"
. "$(dirname "$0")/install-wireguard.sh"

detect_3xui_mode() {
  local platform="$1"

  if [ "$platform" = "linux" ] && [ -f /etc/x-ui/x-ui.db ]; then
    echo "true"
  else
    echo "false"
  fi
}

check_dependencies() {
  local platform="$1"
  local missing=""
  local base_deps="grep cut date tee tar curl jq"
  local platform_deps=""

  if [ "$platform" = "openwrt" ]; then
    platform_deps="uci"
  fi

  for cmd in $base_deps $platform_deps; do
    if ! command -v "$cmd" >/dev/null 2>&1; then
      missing="$missing $cmd"
    fi
  done

  if [ -n "$missing" ]; then
    log "ВНИМАНИЕ: Отсутствуют необходимые утилиты:$missing"

    if [ "$platform" = "linux" ]; then
      log "Устанавливаю недостающие пакеты через apt-get..."

      if command -v apt-get >/dev/null 2>&1; then
        if ! apt-get update; then
          log "ОШИБКА: Не удалось обновить список пакетов apt-get"
          return 1
        fi

        for cmd in $missing; do
          log "Установка $cmd..."
          if ! apt-get install -y "$cmd" 2>/dev/null; then
            log "ПРЕДУПРЕЖДЕНИЕ: Не удалось установить $cmd через apt-get"
          fi
        done
      else
        log "ОШИБКА: apt-get не найден. Невозможно установить зависимости."
        return 1
      fi
    else
      log "Устанавливаю недостающие пакеты через opkg..."

      if command -v opkg >/dev/null 2>&1; then
        if ! opkg update; then
          log "ОШИБКА: Не удалось обновить список пакетов opkg"
          return 1
        fi

        for cmd in $missing; do
          log "Установка $cmd..."
          if ! opkg install "$cmd" 2>/dev/null; then
            log "ПРЕДУПРЕЖДЕНИЕ: Не удалось установить $cmd через opkg"
          fi
        done
      else
        log "ОШИБКА: opkg не найден. Невозможно установить зависимости."
        return 1
      fi
    fi
  fi

  return 0
}

setup_configs() {
  log "Настройка конфигураций..."

  mkdir -p "$PHOBOS_DIR"

  cp wg-obfuscator.conf "$PHOBOS_DIR/${OBF_CONF_NAME}"
  chmod 600 "$PHOBOS_DIR/${OBF_CONF_NAME}"

  cp "${CLIENT_NAME}.conf" "$PHOBOS_DIR/${CLIENT_NAME}.conf"
  chmod 600 "$PHOBOS_DIR/${CLIENT_NAME}.conf"

  printf '%s' "${CLIENT_NAME}" > "$PHOBOS_DIR/${OBF_CONF_NAME%.conf}.link"

  if [ "$OBF_BINARY_NAME" != "wg-obfuscator" ]; then
    local used_ports=""
    for existing_conf in "$PHOBOS_DIR"/wg-obfuscator*.conf; do
      [ -f "$existing_conf" ] || continue
      [ "$(basename "$existing_conf")" = "${OBF_CONF_NAME}" ] && continue
      local port
      port=$(grep 'source-lport' "$existing_conf" 2>/dev/null | tr -d ' ' | cut -d'=' -f2)
      [ -n "$port" ] && used_ports="${used_ports} ${port}"
    done

    local new_port=13255
    local port_taken=1
    while [ "$port_taken" -eq 1 ]; do
      port_taken=0
      for p in $used_ports; do
        if [ "$p" = "$new_port" ]; then
          port_taken=1
          new_port=$((new_port + 1))
          break
        fi
      done
    done

    sed -i "s/^source-lport = [0-9]*/source-lport = ${new_port}/" "$PHOBOS_DIR/${OBF_CONF_NAME}"
    sed -i "s/^Endpoint = 127\.0\.0\.1:[0-9]*/Endpoint = 127.0.0.1:${new_port}/" "$PHOBOS_DIR/${CLIENT_NAME}.conf"

    log "  Назначен локальный порт obfuscator: $new_port"
  fi

  log "Конфигурации установлены:"
  log "  - Obfuscator: $PHOBOS_DIR/${OBF_CONF_NAME}"
  log "  - WireGuard: $PHOBOS_DIR/${CLIENT_NAME}.conf"
}

deploy_lib_client() {
  if [ -f "lib-client.sh" ]; then
    cp "lib-client.sh" "$PHOBOS_DIR/lib-client.sh"
  fi
}


deploy_uninstall_script() {
  log "Развертывание скрипта удаления Phobos..."

  if [ -f "phobos-uninstall.sh" ]; then
    cp "phobos-uninstall.sh" "$PHOBOS_DIR/phobos-uninstall.sh"
    chmod +x "$PHOBOS_DIR/phobos-uninstall.sh"
    log "Скрипт удаления установлен: $PHOBOS_DIR/phobos-uninstall.sh"
  else
    log "ПРЕДУПРЕЖДЕНИЕ: phobos-uninstall.sh не найден в архиве"
  fi
}

deploy_3xui_script() {
  log "Развертывание скрипта 3xui.sh..."

  if [ -f "3xui.sh" ]; then
    cp "3xui.sh" "$PHOBOS_DIR/3xui.sh"
    chmod +x "$PHOBOS_DIR/3xui.sh"
    log "Скрипт 3xui.sh установлен: $PHOBOS_DIR/3xui.sh"
  else
    log "ПРЕДУПРЕЖДЕНИЕ: 3xui.sh не найден в архиве"
  fi
}

run_3xui_integration() {
  log ""
  log "==> Интеграция WireGuard конфигурации в 3x-ui..."

  if [ ! -f "$PHOBOS_DIR/3xui.sh" ]; then
    log "ОШИБКА: Скрипт $PHOBOS_DIR/3xui.sh не найден"
    return 1
  fi

  for cmd in jq sqlite3; do
    if ! command -v "$cmd" >/dev/null 2>&1; then
      log "Устанавливаю $cmd..."
      if command -v apt-get >/dev/null 2>&1; then
        apt-get update -qq && apt-get install -y -qq "$cmd" >/dev/null 2>&1
      elif command -v yum >/dev/null 2>&1; then
        yum install -y -q "${cmd/sqlite3/sqlite}" >/dev/null 2>&1
      elif command -v dnf >/dev/null 2>&1; then
        dnf install -y -q "${cmd/sqlite3/sqlite}" >/dev/null 2>&1
      elif command -v apk >/dev/null 2>&1; then
        apk add --quiet "${cmd/sqlite3/sqlite}" >/dev/null 2>&1
      fi
      if ! command -v "$cmd" >/dev/null 2>&1; then
        log "ОШИБКА: не удалось установить $cmd"
        return 1
      fi
    fi
  done

  local wg_config="$PHOBOS_DIR/${CLIENT_NAME}.conf"

  if [ ! -f "$wg_config" ]; then
    log "ОШИБКА: Конфигурация WireGuard не найдена: $wg_config"
    return 1
  fi

  log "Запуск интеграции: $PHOBOS_DIR/3xui.sh $wg_config"

  if "$PHOBOS_DIR/3xui.sh" "$wg_config"; then
    log "[OK] WireGuard конфигурация успешно интегрирована в 3x-ui"
    log "[OK] Outbound 'Phobos' добавлен в конфигурацию 3x-ui"
    return 0
  else
    log "ОШИБКА: Не удалось интегрировать конфигурацию в 3x-ui"
    return 1
  fi
}

cleanup_3xui_script() {
  local keep_script="$1"

  if [ "$keep_script" = "true" ]; then
    log "Скрипт 3xui.sh сохранен для использования в 3x-ui режиме"
  else
    if [ -f "$PHOBOS_DIR/3xui.sh" ]; then
      rm -f "$PHOBOS_DIR/3xui.sh"
      log "Скрипт 3xui.sh удален (не требуется в обычном режиме)"
    fi
  fi
}

install_wireguard_openwrt() {
  log "Установка пакетов WireGuard для OpenWRT..."

  if ! command -v wg >/dev/null 2>&1; then
    log "Установка kmod-wireguard и wireguard-tools..."
    opkg update
    opkg install kmod-wireguard wireguard-tools luci-proto-wireguard
  else
    log "WireGuard уже установлен"
  fi

  log "Установка luci-app-wireguard для веб-интерфейса..."
  opkg install luci-app-wireguard >/dev/null 2>&1 || log "ПРЕДУПРЕЖДЕНИЕ: luci-app-wireguard не удалось установить"

  log "✓ Пакеты WireGuard установлены"
}

configure_wireguard_openwrt() {
  log ""
  log "==> Автоматическая настройка WireGuard через UCI..."

  extract_wireguard_params

  if [ ! -f "./router-configure-wireguard-openwrt.sh" ]; then
    log "⚠ Скрипт router-configure-wireguard-openwrt.sh не найден"
    log "   Используйте ручную настройку через LuCI или UCI"
    return 1
  fi

  chmod +x ./router-configure-wireguard-openwrt.sh

  if ./router-configure-wireguard-openwrt.sh \
      --client-name "$CLIENT_NAME" \
      --client-private-key "$WG_PRIVATE_KEY" \
      --client-ip "$CLIENT_IP" \
      --client-ipv6 "$CLIENT_IPV6" \
      --server-public-key "$WG_SERVER_PUBKEY" \
      --endpoint-port "$WG_ENDPOINT_PORT" \
      --keepalive 25 \
      --mtu 1420 \
      --fallback-config "$PHOBOS_DIR/${CLIENT_NAME}.conf"; then

    return 0
  else
    return 1
  fi
}

extract_wireguard_params() {
  log "Извлечение параметров WireGuard из конфигурации..."

  local config_file="$PHOBOS_DIR/${CLIENT_NAME}.conf"

  WG_PRIVATE_KEY=$(grep '^PrivateKey' "$config_file" | cut -d'=' -f2- | tr -d ' \t\n\r')
  WG_ADDRESS=$(grep '^Address' "$config_file" | cut -d'=' -f2- | tr -d ' \t\n\r')
  WG_SERVER_PUBKEY=$(grep '^PublicKey' "$config_file" | cut -d'=' -f2- | tr -d ' \t\n\r')
  WG_ENDPOINT_PORT=$(grep '^Endpoint' "$config_file" | cut -d':' -f2 | tr -d ' \t\n\r')

  CLIENT_IP=$(echo "$WG_ADDRESS" | cut -d',' -f1 | tr -d ' ')
  CLIENT_IPV6=$(echo "$WG_ADDRESS" | cut -d',' -f2 | tr -d ' ')

  if [ -z "$CLIENT_IPV6" ] || [ "$CLIENT_IPV6" = "$CLIENT_IP" ]; then
    CLIENT_IPV6=$(grep -A 10 '\[Interface\]' "$config_file" | grep '^Address' | grep -o 'fd[0-9a-f:\/]*' | head -1)
  fi

  if [ -z "$CLIENT_IPV6" ]; then
    CLIENT_IPV6="none"
  fi

  if [ -z "$WG_ENDPOINT_PORT" ]; then
    WG_ENDPOINT_PORT=13255
  fi

  log "  Private Key: ${WG_PRIVATE_KEY:0:20}..."
  log "  IPv4: $CLIENT_IP"
  log "  IPv6: $CLIENT_IPV6"
  log "  Server PubKey: ${WG_SERVER_PUBKEY:0:20}..."
  log "  Endpoint port: $WG_ENDPOINT_PORT"
}

configure_wireguard_rci() {
  log ""
  log "==> Автоматическая настройка WireGuard через RCI API..."

  extract_wireguard_params

  if [ ! -f "./router-configure-wireguard.sh" ]; then
    log "⚠ Скрипт router-configure-wireguard.sh не найден"
    log "   Используйте ручной импорт (см. инструкции ниже)"
    return 1
  fi

  chmod +x ./router-configure-wireguard.sh

  if ./router-configure-wireguard.sh \
      --client-name "$CLIENT_NAME" \
      --client-private-key "$WG_PRIVATE_KEY" \
      --client-ip "$CLIENT_IP" \
      --client-ipv6 "$CLIENT_IPV6" \
      --server-public-key "$WG_SERVER_PUBKEY" \
      --endpoint-port "$WG_ENDPOINT_PORT" \
      --keepalive 25 \
      --mtu 1420 \
      --fallback-config "$PHOBOS_DIR/${CLIENT_NAME}.conf"; then

    return 0
  else
    return 1
  fi
}

show_manual_instructions() {
  log ""
  log "╔════════════════════════════════════════════════════════════╗"
  log "║  Требуется ручной импорт WireGuard конфигурации            ║"
  log "╚════════════════════════════════════════════════════════════╝"
  log ""
  log "Выполните следующие шаги:"
  log ""

  if [ "$ROUTER_PLATFORM" = "keenetic" ]; then
    log "1. Откройте веб-панель администрирования роутера Keenetic"
    log "   (http://192.168.1.1 или http://my.keenetic.net)"
    log ""
    log "2. Перейдите в раздел: Интернет → Другие подключения"
    log ""
    log "3. Выберите 'Загрузить конфигурацию из файла' в разделе 'WireGuard'"
    log ""
    log "4. Укажите путь к файлу:"
    log "   $PHOBOS_DIR/${CLIENT_NAME}.conf"
    log ""
    log "5. Активируйте подключение"
  elif [ "$ROUTER_PLATFORM" = "openwrt" ]; then
    log "1. Откройте веб-интерфейс LuCI роутера OpenWRT"
    log "   (обычно http://192.168.1.1)"
    log ""
    log "2. Перейдите в: Network → Interfaces"
    log ""
    log "3. Создайте новый интерфейс с протоколом WireGuard"
    log ""
    log "4. Используйте параметры из файла:"
    log "   $PHOBOS_DIR/${CLIENT_NAME}.conf"
    log ""
    log "5. Настройте файрволл зону для интерфейса"
  fi

  log ""
}

show_final_info() {
  log ""
  log "╔════════════════════════════════════════════════════════════╗"
  log "║  Информация об установке                                   ║"
  log "╚════════════════════════════════════════════════════════════╝"
  log ""
  log "Файлы установки:"

  if [ "$ROUTER_PLATFORM" = "keenetic" ]; then
    log "  Бинарник: /opt/bin/${OBF_BINARY_NAME}"
  elif [ "$ROUTER_PLATFORM" = "openwrt" ]; then
    log "  Бинарник: /usr/bin/${OBF_BINARY_NAME}"
  elif [ "$ROUTER_PLATFORM" = "linux" ]; then
    log "  Бинарник: /usr/local/bin/${OBF_BINARY_NAME}"
  fi

  log "  Конфиг obfuscator: $PHOBOS_DIR/${OBF_CONF_NAME}"
  log "  Конфиг WireGuard: $PHOBOS_DIR/${CLIENT_NAME}.conf"

  if [ "$ROUTER_PLATFORM" = "keenetic" ] || [ -f /opt/etc/init.d/${OBF_INIT_NAME} ]; then
    log "  Init-скрипт: /opt/etc/init.d/${OBF_INIT_NAME}"
  elif [ "$ROUTER_PLATFORM" = "openwrt" ] && [ -f /etc/init.d/${OBF_SERVICE_NAME} ]; then
    log "  Init-скрипт: /etc/init.d/${OBF_SERVICE_NAME}"
  elif [ "$ROUTER_PLATFORM" = "linux" ]; then
    log "  Systemd service: /etc/systemd/system/${OBF_SERVICE_NAME}.service"
    log "  WireGuard конфиг: /etc/wireguard/${OBF_WG_IFACE}.conf"
  fi

  log "  Uninstall: $PHOBOS_DIR/phobos-uninstall.sh"
  log ""
  log "Управление:"

  if [ "$ROUTER_PLATFORM" = "keenetic" ] || [ -f /opt/etc/init.d/${OBF_INIT_NAME} ]; then
    log "  /opt/etc/init.d/${OBF_INIT_NAME} status    # Проверить что obfuscator запущен"
  elif [ "$ROUTER_PLATFORM" = "openwrt" ] && [ -f /etc/init.d/${OBF_SERVICE_NAME} ]; then
    log "  /etc/init.d/${OBF_SERVICE_NAME} status       # Проверить что obfuscator запущен"
  elif [ "$ROUTER_PLATFORM" = "linux" ]; then
    log "  systemctl status ${OBF_SERVICE_NAME}         # Проверить что obfuscator запущен"
    log "  systemctl status wg-quick@${OBF_WG_IFACE}           # Проверить что WireGuard запущен"
  fi

  log "  $PHOBOS_DIR/phobos-uninstall.sh     # Удалить Phobos"
  log ""
}

main() {
  ROUTER_PLATFORM=$(detect_router_platform)
  PHOBOS_DIR=$(detect_phobos_dir "$ROUTER_PLATFORM")
  IS_3XUI_MODE=$(detect_3xui_mode "$ROUTER_PLATFORM")

  log "==> Определена платформа: $ROUTER_PLATFORM"
  log "==> Директория Phobos: $PHOBOS_DIR"

  resolve_install_names
  log "==> Режим установки obfuscator: binary=${OBF_BINARY_NAME}, conf=${OBF_CONF_NAME}, init=${OBF_INIT_NAME}, service=${OBF_SERVICE_NAME}"

  if [ "$IS_3XUI_MODE" = "true" ]; then
    log "==> Обнаружен режим установки: 3x-ui"
    log "==> В этом режиме WireGuard не устанавливается"
    log "==> Будет развернут только wg-obfuscator и интеграция с 3x-ui"
  fi

  if [ "$ROUTER_PLATFORM" = "unknown" ]; then
    log "ОШИБКА: Неподдерживаемая платформа"
    log "Вывод uname -a: $(uname -a)"
    log ""
    log "Поддерживаемые платформы:"
    log "  - Keenetic/Netcraze (определяется по 'Keenetic' или 'Netcraze' в uname)"
    log "  - OpenWRT (определяется по 'OpenWrt', 'LEDE' или 'ImmortalWrt' в uname)"
    log "  - Linux (Ubuntu/Debian)"
    exit 1
  fi

  mkdir -p "$PHOBOS_DIR"
  log "==> Начало установки Phobos на роутер $ROUTER_PLATFORM"
  log "==> Клиент: $CLIENT_NAME"

  check_root

  if ! check_dependencies "$ROUTER_PLATFORM"; then
    log "ОШИБКА: Не удалось установить зависимости"
    exit 1
  fi

  ARCH=$(detect_arch)
  log "Определена архитектура: $ARCH"

  if [ "$ARCH" = "unknown" ]; then
    log "Ошибка: неподдерживаемая архитектура"
    log "Вывод uname -m: $(uname -m)"
    exit 1
  fi

  install_obfuscator "$ARCH"
  setup_configs
  deploy_lib_client
  deploy_uninstall_script

  if [ "$IS_3XUI_MODE" = "true" ]; then
    deploy_3xui_script
  fi

  if [ "$ROUTER_PLATFORM" = "keenetic" ]; then
    create_init_script
    start_obfuscator

    if configure_wireguard_rci; then
      log ""
      log "╔════════════════════════════════════════════════════════════╗"
      log "║  ✓ Установка завершена успешно!                            ║"
      log "║  ✓ WireGuard настроен автоматически через RCI API          ║"
      log "╚════════════════════════════════════════════════════════════╝"
      show_final_info
    else
      log ""
      log "╔════════════════════════════════════════════════════════════╗"
      log "║  ✓ Obfuscator установлен успешно                           ║"
      log "║  ⚠ WireGuard требует ручной настройки                     ║"
      log "╚════════════════════════════════════════════════════════════╝"
      show_manual_instructions
      show_final_info
    fi

  elif [ "$ROUTER_PLATFORM" = "openwrt" ]; then
    install_wireguard_openwrt

    if [ -d "/opt/etc" ]; then
      create_init_script
    else
      create_procd_init_script
    fi

    start_obfuscator

    if configure_wireguard_openwrt; then
      log ""
      log "╔════════════════════════════════════════════════════════════╗"
      log "║  ✓ Установка завершена успешно!                            ║"
      log "║  ✓ WireGuard настроен автоматически через UCI              ║"
      log "╚════════════════════════════════════════════════════════════╝"
      show_final_info
    else
      log ""
      log "╔════════════════════════════════════════════════════════════╗"
      log "║  ✓ Obfuscator установлен успешно                           ║"
      log "║  ⚠ WireGuard требует ручной настройки                     ║"
      log "╚════════════════════════════════════════════════════════════╝"
      show_manual_instructions
      show_final_info
    fi

  elif [ "$ROUTER_PLATFORM" = "linux" ]; then
    if [ "$IS_3XUI_MODE" = "true" ]; then
      log ""
      log "╔════════════════════════════════════════════════════════════╗"
      log "║  Режим установки: 3x-ui                                    ║"
      log "╚════════════════════════════════════════════════════════════╝"
      log ""

      create_systemd_obfuscator_service

      if run_3xui_integration; then
        cleanup_3xui_script "true"
        log ""
        log "╔════════════════════════════════════════════════════════════╗"
        log "║  ✓ Установка в режиме 3x-ui завершена успешно!            ║"
        log "║  ✓ Obfuscator настроен через systemd                      ║"
        log "║  ✓ Outbound 'Phobos' добавлен в конфигурацию 3x-ui        ║"
        log "╚════════════════════════════════════════════════════════════╝"
        log ""
        log "Файлы установки:"
        log "  Бинарник: /usr/local/bin/wg-obfuscator"
        log "  Конфиг obfuscator: $PHOBOS_DIR/wg-obfuscator.conf"
        log "  Конфиг WireGuard: $PHOBOS_DIR/${CLIENT_NAME}.conf"
        log "  Скрипт 3xui.sh: $PHOBOS_DIR/3xui.sh"
        log "  Systemd service: /etc/systemd/system/phobos-obfuscator.service"
        log ""
        log "Управление:"
        log "  systemctl status phobos-obfuscator         # Проверить что obfuscator запущен"
        log ""
        log "Примечание:"
        log "  WireGuard управляется через 3x-ui панель"
        log "  Скрипт 3xui.sh сохранен для повторной интеграции при необходимости"
        log ""
      else
        log ""
        log "╔════════════════════════════════════════════════════════════╗"
        log "║  ✗ Установка в режиме 3x-ui завершена с ошибками          ║"
        log "╚════════════════════════════════════════════════════════════╝"
        exit 1
      fi
    else
      install_wireguard_linux || {
        log "ОШИБКА: Не удалось установить WireGuard"
        exit 1
      }

      create_systemd_obfuscator_service

      if configure_wireguard_linux; then
        configure_ufw_linux
        cleanup_3xui_script "false"
        log ""
        log "╔════════════════════════════════════════════════════════════╗"
        log "║  ✓ Установка завершена успешно!                            ║"
        log "║  ✓ WireGuard и Obfuscator настроены через systemd         ║"
        log "╚════════════════════════════════════════════════════════════╝"
        show_final_info
      else
        cleanup_3xui_script "false"
        log ""
        log "╔════════════════════════════════════════════════════════════╗"
        log "║  ⚠ Установка завершена с предупреждениями                 ║"
        log "║  ⚠ Проверьте статус служб вручную                         ║"
        log "╚════════════════════════════════════════════════════════════╝"
        show_final_info
      fi
    fi
  fi

  log "==> Установка завершена."
}

main "$@"