diff --git a/install_ssh_tunnel.sh b/install_ssh_tunnel.sh index d6d06ef..5eccc3a 100644 --- a/install_ssh_tunnel.sh +++ b/install_ssh_tunnel.sh @@ -33,14 +33,20 @@ if [[ $EUID -ne 0 ]]; then exit 1 fi -# Функция безопасного ввода +# Функция безопасного ввода с ограничением попыток safe_read() { local prompt="$1" local default="$2" local var_name="$3" local is_password="$4" + local max_attempts="${5:-3}" # По умолчанию 3 попытки - while true; do + local attempt=0 + local input="" + + while [[ $attempt -lt $max_attempts ]]; do + attempt=$((attempt + 1)) + if [ "$is_password" = "yes" ]; then read -s -p "$prompt" input echo @@ -53,10 +59,14 @@ safe_read() { if [ -n "$input" ]; then eval "$var_name=\"$input\"" return 0 - else - echo -e "${RED}Поле не может быть пустым!${NC}" + elif [[ $attempt -lt $max_attempts ]]; then + echo -e "${YELLOW}Поле не может быть пустым! Попытка $attempt из $max_attempts${NC}" fi done + + # Если превышено количество попыток + echo -e "${RED}Превышено максимальное количество попыток ввода. Выход.${NC}" + exit 1 } # Функция проверки ошибок @@ -64,6 +74,14 @@ check_error() { if [ $? -ne 0 ]; then log_message "ОШИБКА: $1" "$RED" log_message "Подробности в логе: $LOG_FILE" "$YELLOW" + + # Не выходим сразу, а даем пользователю выбор + echo -e "${YELLOW}Произошла ошибка: $1${NC}" + read -p "Продолжить установку? (y/n): " -n 1 -r + echo + if [[ ! $REPLY =~ ^[Yy]$ ]]; then + exit 1 + fi return 1 fi return 0 @@ -86,6 +104,7 @@ detect_distro() { fi log_message "Система: $OS $VERSION" "$GREEN" + return 0 } # Установка зависимостей @@ -95,7 +114,9 @@ install_dependencies() { case $OS in ubuntu|debian) log_message "Обновление списка пакетов..." "$BLUE" - apt-get update 2>&1 | tee -a "$LOG_FILE" + if ! apt-get update 2>&1 | tee -a "$LOG_FILE"; then + echo -e "${YELLOW}Предупреждение: не удалось обновить список пакетов${NC}" + fi log_message "Установка autossh, openssh-client и утилит..." "$BLUE" apt-get install -y autossh openssh-client net-tools curl git sshpass 2>&1 | tee -a "$LOG_FILE" @@ -117,17 +138,21 @@ install_dependencies() { # Попытка установить autossh из исходников if ! command -v autossh &> /dev/null; then log_message "Установка autossh вручную..." "$BLUE" - curl -sSL http://www.harding.motd.ca/autossh/autossh-1.4g.tgz | tar -xz - cd autossh-1.4g || exit 1 - ./configure - make - make install - cd .. + if curl -sSL http://www.harding.motd.ca/autossh/autossh-1.4g.tgz | tar -xz; then + cd autossh-1.4g || exit 1 + ./configure + make + make install + cd .. + else + echo -e "${YELLOW}Не удалось загрузить autossh${NC}" + fi fi ;; esac log_message "Зависимости успешно установлены!" "$GREEN" + return 0 } # Настройка SSH @@ -145,23 +170,42 @@ setup_ssh() { echo -e "${BOLD}${YELLOW}════════════════════════════════════════════════════════════════${NC}" echo "" - # Запрос данных VPS - while true; do - echo -e "${CYAN}Введите данные для подключения к VPS:${NC}" - safe_read "IP адрес или доменное имя VPS: " "" VPS_HOST no - safe_read "Порт SSH (по умолчанию 22): " "22" VPS_PORT no + # Запрос данных VPS с проверкой + local vps_data_ok=false + local max_attempts=3 + + for ((attempt=1; attempt<=max_attempts; attempt++)); do + echo -e "${CYAN}Введите данные для подключения к VPS (попытка $attempt из $max_attempts):${NC}" + + # Используем обычный read для предотвращения конфликтов с safe_read + read -p "IP адрес или доменное имя VPS: " VPS_HOST + read -p "Порт SSH (по умолчанию 22): " VPS_PORT + VPS_PORT=${VPS_PORT:-22} echo "" echo -e "${CYAN}Выберите пользователя для подключения:${NC}" echo "1) root (рекомендуется для полного доступа)" echo "2) Другой пользователь" - safe_read "Ваш выбор [1-2]: " "1" USER_CHOICE no + read -p "Ваш выбор [1-2]: " USER_CHOICE if [ "$USER_CHOICE" == "1" ]; then VPS_USER="root" echo -e "${YELLOW}Будет использоваться пользователь: root${NC}" else - safe_read "Введите имя пользователя: " "" VPS_USER no + read -p "Введите имя пользователя: " VPS_USER + fi + + # Проверка заполнения обязательных полей + if [[ -z "$VPS_HOST" || -z "$VPS_USER" ]]; then + echo -e "${RED}Ошибка: обязательные поля не заполнены!${NC}" + if [[ $attempt -lt $max_attempts ]]; then + echo -e "${YELLOW}Пожалуйста, заполните все поля.${NC}" + echo "" + continue + else + echo -e "${RED}Превышено максимальное количество попыток. Выход.${NC}" + exit 1 + fi fi echo "" @@ -169,9 +213,10 @@ setup_ssh() { echo -e " VPS: ${YELLOW}$VPS_USER@$VPS_HOST:$VPS_PORT${NC}" echo "" - safe_read "Все верно? (y/n): " "y" CONFIRM no + read -p "Все верно? (y/n): " CONFIRM if [[ "$CONFIRM" =~ ^[Yy]$ ]]; then + vps_data_ok=true break else echo -e "${YELLOW}Повторите ввод данных...${NC}" @@ -179,6 +224,11 @@ setup_ssh() { fi done + if [ "$vps_data_ok" = false ]; then + echo -e "${RED}Не удалось получить корректные данные VPS. Выход.${NC}" + exit 1 + fi + # Проверка подключения log_message "Проверка подключения к $VPS_USER@$VPS_HOST:$VPS_PORT..." "$BLUE" echo -e "${CYAN}Пытаюсь подключиться к VPS...${NC}" @@ -193,7 +243,7 @@ setup_ssh() { echo -e " 3) Работает ли SSH сервер на VPS" echo -e " 4) Не блокирует ли брандмауэр подключение" - safe_read "Продолжить все равно? (y/n): " "n" CONTINUE no + read -p "Продолжить все равно? (y/n): " CONTINUE if [[ ! "$CONTINUE" =~ ^[Yy]$ ]]; then exit 1 @@ -206,7 +256,7 @@ setup_ssh() { if [ -f "/root/.ssh/id_rsa" ]; then echo -e "${YELLOW}SSH ключ уже существует.${NC}" - safe_read "Сгенерировать новый? (y/n): " "n" GEN_NEW no + read -p "Сгенерировать новый? (y/n): " GEN_NEW if [[ "$GEN_NEW" =~ ^[Yy]$ ]]; then ssh-keygen -t rsa -b 4096 -N "" -f /root/.ssh/id_rsa -q @@ -221,7 +271,7 @@ setup_ssh() { log_message "Настройка конфигурации SSH для стабильного подключения..." "$BLUE" # Создание конфига для root с улучшенными настройками - cat > /root/.ssh/config << EOF + cat > /root/.ssh/config << EOFCONFIG # Основная конфигурация SSH Host tunnel-vps HostName $VPS_HOST @@ -269,7 +319,7 @@ Host * HashKnownHosts yes # Настройки переподключения RekeyLimit 1G 1h -EOF +EOFCONFIG chmod 600 /root/.ssh/config @@ -321,7 +371,8 @@ EOF echo -e "${YELLOW}Для копирования ключа потребуется пароль от $VPS_USER на VPS${NC}" # Запрос пароля для копирования ключа - safe_read "Введите пароль для $VPS_USER@$VPS_HOST (или нажмите Enter для пропуска): " "" VPS_PASSWORD yes + read -s -p "Введите пароль для $VPS_USER@$VPS_HOST (или нажмите Enter для пропуска): " VPS_PASSWORD + echo if [ -n "$VPS_PASSWORD" ]; then echo "" @@ -329,10 +380,10 @@ EOF # Установка SSH_ASKPASS для автоматического ввода пароля export SSH_ASKPASS="$(mktemp)" - cat > "$SSH_ASKPASS" << EOF + cat > "$SSH_ASKPASS" << EOFASKPASS #!/bin/bash echo "$VPS_PASSWORD" -EOF +EOFASKPASS chmod +x "$SSH_ASKPASS" export DISPLAY=:0 @@ -371,7 +422,7 @@ EOF echo -e "${BOLD}chmod 600 ~/.ssh/authorized_keys${NC}" echo "" - safe_read "Нажмите Enter после добавления ключа на VPS..." "" WAIT no + read -p "Нажмите Enter после добавления ключа на VPS..." WAIT # Тестовое подключение log_message "Тестовое подключение к VPS..." "$BLUE" @@ -390,7 +441,7 @@ EOF echo -e "${YELLOW}⚠ Не удалось подключиться без пароля${NC}" echo -e "${YELLOW}Убедитесь, что ключ добавлен в authorized_keys на VPS${NC}" - safe_read "Продолжить установку? (y/n): " "y" CONTINUE_INSTALL no + read -p "Продолжить установку? (y/n): " CONTINUE_INSTALL if [[ ! "$CONTINUE_INSTALL" =~ ^[Yy]$ ]]; then exit 1 @@ -400,7 +451,7 @@ EOF # Настройка для не-root пользователей if [[ $EUID -eq 0 ]] && [ -d "/home/" ] && [ "$(ls -A /home/ 2>/dev/null)" ]; then echo "" - safe_read "Настроить SSH для обычных пользователей системы? (y/n): " "n" SETUP_USERS no + read -p "Настроить SSH для обычных пользователей системы? (y/n): " SETUP_USERS if [[ "$SETUP_USERS" =~ ^[Yy]$ ]]; then log_message "Настройка SSH для всех пользователей системы..." "$CYAN" @@ -424,7 +475,7 @@ EOF echo -e " ${GREEN}✓ Конфиг скопирован${NC}" fi - safe_read " Скопировать SSH ключ для пользователя $USER? (y/n): " "n" COPY_FOR_USER no + read -p " Скопировать SSH ключ для пользователя $USER? (y/n): " COPY_FOR_USER if [[ "$COPY_FOR_USER" =~ ^[Yy]$ ]]; then cp /root/.ssh/id_rsa* "$USER_SSH_DIR/" 2>/dev/null @@ -442,16 +493,17 @@ EOF log_message "Сохранение настроек VPS..." "$BLUE" mkdir -p /etc/ssh_tunnel - cat > /etc/ssh_tunnel/vps_settings.conf << EOF + cat > /etc/ssh_tunnel/vps_settings.conf << EOFSETTINGS # Настройки VPS для автономных туннелей VPS_HOST="$VPS_HOST" VPS_PORT="$VPS_PORT" VPS_USER="$VPS_USER" CONFIGURED_ON="$(date '+%Y-%m-%d %H:%M:%S')" -EOF +EOFSETTINGS chmod 600 /etc/ssh_tunnel/vps_settings.conf log_message "Настройки SSH сохранены в /etc/ssh_tunnel/vps_settings.conf" "$GREEN" + return 0 } # Установка основного скрипта управления @@ -1267,6 +1319,7 @@ EOFCOLORS ln -sf /opt/ssh_tunnel_manager/manager.sh /usr/local/bin/tunnel-manager 2>/dev/null log_message "Основной скрипт установлен в /opt/ssh_tunnel_manager/" "$GREEN" + return 0 } # Настройка systemd служб @@ -1381,6 +1434,7 @@ EOFTIMER systemctl start tunnel-check.timer 2>/dev/null log_message "Systemd службы настроены" "$GREEN" + return 0 } # Создание примера туннеля @@ -1388,7 +1442,7 @@ create_example_tunnel() { log_message "Создание примера SSH туннеля..." "$CYAN" if [ -n "$VPS_HOST" ] && [ -n "$VPS_USER" ]; then - safe_read "Создать пример туннеля для SSH (порт 22 -> 10022)? (y/n): " "y" CREATE_EXAMPLE no + read -p "Создать пример туннеля для SSH (порт 22 -> 10022)? (y/n): " CREATE_EXAMPLE if [[ "$CREATE_EXAMPLE" =~ ^[Yy]$ ]]; then cat > /etc/ssh_tunnel/example_ssh.conf << EOFEXAMPLE @@ -1445,6 +1499,7 @@ EOFEXSERVICE echo -e " tail -f /var/log/ssh_tunnel/example_ssh.log" fi fi + return 0 } # Завершение установки @@ -1485,7 +1540,7 @@ finish_installation() { echo "" # Запрос на перезагрузку - safe_read "Перезагрузить систему для применения всех настроек? (y/n): " "n" REBOOT_NOW no + read -p "Перезагрузить систему для применения всех настроек? (y/n): " REBOOT_NOW if [[ "$REBOOT_NOW" =~ ^[Yy]$ ]]; then log_message "Перезагрузка системы по запросу пользователя..." "$YELLOW" @@ -1498,6 +1553,7 @@ finish_installation() { echo -e "${BOLD}tunnel-manager${NC}" echo "" fi + return 0 } # Главная функция установки @@ -1505,26 +1561,48 @@ main_installation() { log_message "Начало установки автономного менеджера SSH туннелей" "$CYAN" # Определяем дистрибутив - detect_distro + detect_distro || { + echo -e "${RED}Не удалось определить дистрибутив${NC}" + exit 1 + } # Устанавливаем зависимости - install_dependencies + install_dependencies || { + echo -e "${RED}Не удалось установить зависимости${NC}" + exit 1 + } - # Настраиваем SSH (теперь будет запрашивать данные) - setup_ssh + # Настраиваем SSH + setup_ssh || { + echo -e "${RED}Не удалось настроить SSH${NC}" + exit 1 + } # Устанавливаем основной скрипт - install_main_script + install_main_script || { + echo -e "${RED}Не удалось установить основной скрипт${NC}" + exit 1 + } # Настраиваем systemd службы - setup_systemd_services + setup_systemd_services || { + echo -e "${YELLOW}Не удалось настроить systemd службы${NC}" + } # Создаем пример туннеля - create_example_tunnel + create_example_tunnel || { + echo -e "${YELLOW}Не удалось создать пример туннеля${NC}" + } # Завершаем установку finish_installation } +# Обработка ошибок и трассировка +set -eE +trap 'echo -e "${RED}Произошла ошибка в строке $LINENO. Проверьте лог: $LOG_FILE${NC}"' ERR + # Запуск установки -main_installation \ No newline at end of file +main_installation + +exit 0 \ No newline at end of file