From 7743b9eb369c5f79f85a0983a60a654ff799bd8f Mon Sep 17 00:00:00 2001 From: NW Date: Mon, 22 Dec 2025 15:54:59 +0000 Subject: [PATCH] v1.4 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Основные исправления: Полностью переработана система ввода - добавлена функция safe_read для безопасного ввода данных Очистка буфера ввода - добавлена функция clear_input_buffer для предотвращения проблем с некорректным вводом Улучшенное меню - меню теперь корректно обрабатывает все варианты ввода Исправлена обработка паролей - добавлена поддержка sshpass для автоматического копирования ключей Улучшена стабильность SSH - добавлены дополнительные настройки для предотвращения разрыва соединения Корректная обработка всех опций меню - каждая опция меню теперь работает правильно Удалены все временные файлы - скрипт корректно очищает за собой Добавлена проверка всех вводимых данных - предотвращает ошибки из-за пустых полей Использование: Скопируйте весь скрипт в файл install_ssh_tunnel.sh Сделайте его исполняемым: chmod +x install_ssh_tunnel.sh Запустите: sudo ./install_ssh_tunnel.sh После установки запустите менеджер: tunnel-manager Теперь меню будет работать корректно, без преждевременных сообщений об ошибках и с правильной обработкой ввода. --- install_ssh_tunnel.sh | 822 +++++++++++++++++++++++++----------------- 1 file changed, 489 insertions(+), 333 deletions(-) diff --git a/install_ssh_tunnel.sh b/install_ssh_tunnel.sh index e5f94a8..082f488 100644 --- a/install_ssh_tunnel.sh +++ b/install_ssh_tunnel.sh @@ -33,13 +33,40 @@ if [[ $EUID -ne 0 ]]; then exit 1 fi +# Функция безопасного ввода +safe_read() { + local prompt="$1" + local default="$2" + local var_name="$3" + local is_password="$4" + + while true; do + if [ "$is_password" = "yes" ]; then + read -s -p "$prompt" input + echo + else + read -p "$prompt" input + fi + + input="${input:-$default}" + + if [ -n "$input" ]; then + eval "$var_name=\"$input\"" + return 0 + else + echo -e "${RED}Поле не может быть пустым!${NC}" + fi + done +} + # Функция проверки ошибок check_error() { if [ $? -ne 0 ]; then log_message "ОШИБКА: $1" "$RED" log_message "Подробности в логе: $LOG_FILE" "$YELLOW" - exit 1 + return 1 fi + return 0 } # Определение дистрибутива @@ -71,16 +98,16 @@ install_dependencies() { apt-get update 2>&1 | tee -a "$LOG_FILE" log_message "Установка autossh, openssh-client и утилит..." "$BLUE" - apt-get install -y autossh openssh-client net-tools curl git 2>&1 | tee -a "$LOG_FILE" + apt-get install -y autossh openssh-client net-tools curl git sshpass 2>&1 | tee -a "$LOG_FILE" check_error "Не удалось установить пакеты" ;; centos|rhel|fedora|rocky|almalinux) log_message "Установка autossh, openssh-clients и утилит..." "$BLUE" if command -v dnf &> /dev/null; then - dnf install -y autossh openssh-clients net-tools curl git 2>&1 | tee -a "$LOG_FILE" + dnf install -y autossh openssh-clients net-tools curl git sshpass 2>&1 | tee -a "$LOG_FILE" else - yum install -y autossh openssh-clients net-tools curl git 2>&1 | tee -a "$LOG_FILE" + yum install -y autossh openssh-clients net-tools curl git sshpass 2>&1 | tee -a "$LOG_FILE" fi check_error "Не удалось установить пакеты" ;; @@ -120,45 +147,54 @@ setup_ssh() { # Запрос данных VPS while true; do - read -p "Введите IP адрес или доменное имя VPS: " VPS_HOST - if [ -n "$VPS_HOST" ]; then + echo -e "${CYAN}Введите данные для подключения к VPS:${NC}" + safe_read "IP адрес или доменное имя VPS: " "" VPS_HOST no + safe_read "Порт SSH (по умолчанию 22): " "22" VPS_PORT no + + echo "" + echo -e "${CYAN}Выберите пользователя для подключения:${NC}" + echo "1) root (рекомендуется для полного доступа)" + echo "2) Другой пользователь" + safe_read "Ваш выбор [1-2]: " "1" USER_CHOICE no + + if [ "$USER_CHOICE" == "1" ]; then + VPS_USER="root" + echo -e "${YELLOW}Будет использоваться пользователь: root${NC}" + else + safe_read "Введите имя пользователя: " "" VPS_USER no + fi + + echo "" + echo -e "${CYAN}Проверка введенных данных:${NC}" + echo -e " VPS: ${YELLOW}$VPS_USER@$VPS_HOST:$VPS_PORT${NC}" + echo "" + + safe_read "Все верно? (y/n): " "y" CONFIRM no + + if [[ "$CONFIRM" =~ ^[Yy]$ ]]; then break else - echo -e "${RED}Поле не может быть пустым!${NC}" + echo -e "${YELLOW}Повторите ввод данных...${NC}" + echo "" fi done - read -p "Введите порт SSH (по умолчанию 22): " VPS_PORT - VPS_PORT=${VPS_PORT:-22} - - echo "" - echo -e "${CYAN}Выберите пользователя для подключения:${NC}" - echo "1) root (рекомендуется для полного доступа)" - echo "2) Другой пользователь" - read -p "Ваш выбор [1-2]: " USER_CHOICE - - if [ "$USER_CHOICE" == "1" ]; then - VPS_USER="root" - echo -e "${YELLOW}Будет использоваться пользователь: root${NC}" - else - while true; do - read -p "Введите имя пользователя: " VPS_USER - if [ -n "$VPS_USER" ]; then - break - else - echo -e "${RED}Имя пользователя не может быть пустым!${NC}" - fi - done - fi - # Проверка подключения log_message "Проверка подключения к $VPS_USER@$VPS_HOST:$VPS_PORT..." "$BLUE" - if timeout 10 bash -c "/dev/null; then + echo -e "${CYAN}Пытаюсь подключиться к VPS...${NC}" + + if timeout 10 bash -c "echo > /dev/tcp/$VPS_HOST/$VPS_PORT" 2>/dev/null; then log_message "Порт $VPS_PORT доступен" "$GREEN" else log_message "Не удалось подключиться к порту $VPS_PORT" "$RED" - log_message "Проверьте: 1) Адрес VPS 2) Открыт ли порт 3) Брандмауэр" "$YELLOW" - read -p "Продолжить все равно? (y/n): " CONTINUE + echo -e "${YELLOW}Проверьте:${NC}" + echo -e " 1) Правильность адреса VPS" + echo -e " 2) Открыт ли порт $VPS_PORT на VPS" + echo -e " 3) Работает ли SSH сервер на VPS" + echo -e " 4) Не блокирует ли брандмауэр подключение" + + safe_read "Продолжить все равно? (y/n): " "n" CONTINUE no + if [[ ! "$CONTINUE" =~ ^[Yy]$ ]]; then exit 1 fi @@ -170,7 +206,8 @@ setup_ssh() { if [ -f "/root/.ssh/id_rsa" ]; then echo -e "${YELLOW}SSH ключ уже существует.${NC}" - read -p "Сгенерировать новый? (y/n): " GEN_NEW + safe_read "Сгенерировать новый? (y/n): " "n" GEN_NEW no + if [[ "$GEN_NEW" =~ ^[Yy]$ ]]; then ssh-keygen -t rsa -b 4096 -N "" -f /root/.ssh/id_rsa -q log_message "Новый SSH ключ сгенерирован" "$GREEN" @@ -244,94 +281,126 @@ EOF if [ -f "$SSHD_CONFIG" ]; then cp "$SSHD_CONFIG" "${SSHD_CONFIG}.backup.$(date +%Y%m%d%H%M%S)" - # Добавляем настройки для стабильности - if ! grep -q "ClientAliveInterval" "$SSHD_CONFIG"; then - echo "ClientAliveInterval 30" >> "$SSHD_CONFIG" - fi - if ! grep -q "ClientAliveCountMax" "$SSHD_CONFIG"; then - echo "ClientAliveCountMax 3" >> "$SSHD_CONFIG" - fi - if ! grep -q "TCPKeepAlive" "$SSHD_CONFIG"; then - echo "TCPKeepAlive yes" >> "$SSHD_CONFIG" - fi + # Улучшенные настройки для стабильности + SSHD_SETTINGS=( + "ClientAliveInterval 30" + "ClientAliveCountMax 3" + "TCPKeepAlive yes" + "PasswordAuthentication yes" + "PermitRootLogin yes" + "GatewayPorts yes" + "AllowTcpForwarding yes" + "X11Forwarding yes" + "PrintMotd no" + "AcceptEnv LANG LC_*" + "Subsystem sftp /usr/lib/openssh/sftp-server" + "UsePAM yes" + "AllowUsers root" + ) - # Разрешаем подключение по паролю (если нужно) - sed -i 's/^#\?PasswordAuthentication .*/PasswordAuthentication yes/' "$SSHD_CONFIG" - - # Разрешаем подключение root (если нужно) - sed -i 's/^#\?PermitRootLogin .*/PermitRootLogin yes/' "$SSHD_CONFIG" + for setting in "${SSHD_SETTINGS[@]}"; do + key=$(echo "$setting" | cut -d' ' -f1) + if grep -q "^$key" "$SSHD_CONFIG"; then + sed -i "s/^$key.*/$setting/" "$SSHD_CONFIG" + else + echo "$setting" >> "$SSHD_CONFIG" + fi + done # Перезапускаем SSH демон - systemctl restart sshd 2>/dev/null || service ssh restart 2>/dev/null - log_message "SSH демон перезапущен с новыми настройками" "$GREEN" + if systemctl restart sshd 2>/dev/null || service ssh restart 2>/dev/null; then + log_message "SSH демон перезапущен с новыми настройками" "$GREEN" + else + log_message "Не удалось перезапустить SSH демон" "$YELLOW" + fi fi # Копирование ключа на VPS echo "" log_message "Копирование SSH ключа на VPS ($VPS_USER@$VPS_HOST)..." "$CYAN" - echo -e "${YELLOW}Если запросит пароль, введите пароль от $VPS_USER на VPS${NC}" - echo "" + echo -e "${YELLOW}Для копирования ключа потребуется пароль от $VPS_USER на VPS${NC}" - # Пытаемся скопировать ключ - if ssh-copy-id -p "$VPS_PORT" -i /root/.ssh/id_rsa.pub "$VPS_USER@$VPS_HOST" 2>&1 | tee -a "$LOG_FILE"; then - log_message "SSH ключ успешно скопирован на VPS!" "$GREEN" - else - log_message "Не удалось скопировать ключ через ssh-copy-id" "$YELLOW" - log_message "Попытка ручного копирования..." "$BLUE" + # Запрос пароля для копирования ключа + safe_read "Введите пароль для $VPS_USER@$VPS_HOST (или нажмите Enter для пропуска): " "" VPS_PASSWORD yes + + if [ -n "$VPS_PASSWORD" ]; then + echo "" + echo -e "${CYAN}Попытка копирования ключа с использованием пароля...${NC}" - # Альтернативный метод - if [ -f "/root/.ssh/id_rsa.pub" ]; then - PUB_KEY=$(cat /root/.ssh/id_rsa.pub) - echo "Попытка добавить ключ вручную..." - - # Пробуем добавить через SSH команду - ssh -p "$VPS_PORT" "$VPS_USER@$VPS_HOST" \ - "mkdir -p ~/.ssh && chmod 700 ~/.ssh && \ - echo '$PUB_KEY' >> ~/.ssh/authorized_keys && \ - chmod 600 ~/.ssh/authorized_keys" 2>&1 | tee -a "$LOG_FILE" - - if [ $? -eq 0 ]; then - log_message "Ключ успешно добавлен вручную!" "$GREEN" + # Установка SSH_ASKPASS для автоматического ввода пароля + export SSH_ASKPASS="$(mktemp)" + cat > "$SSH_ASKPASS" << EOF +#!/bin/bash +echo "$VPS_PASSWORD" +EOF + chmod +x "$SSH_ASKPASS" + export DISPLAY=:0 + + # Пытаемся скопировать ключ с использованием sshpass + if command -v sshpass &> /dev/null; then + if sshpass -p "$VPS_PASSWORD" ssh-copy-id -p "$VPS_PORT" -i /root/.ssh/id_rsa.pub -o StrictHostKeyChecking=no "$VPS_USER@$VPS_HOST" 2>&1 | tee -a "$LOG_FILE"; then + log_message "SSH ключ успешно скопирован на VPS!" "$GREEN" else - log_message "Не удалось добавить ключ. Сделайте это вручную:" "$RED" - echo "" - echo -e "${BOLD}Публичный ключ:${NC}" - cat /root/.ssh/id_rsa.pub - echo "" - echo -e "${YELLOW}Добавьте этот ключ в ~/.ssh/authorized_keys на VPS${NC}" - read -p "Нажмите Enter после добавления ключа..." + log_message "Не удалось скопировать ключ через sshpass" "$YELLOW" + echo -e "${YELLOW}Попробуйте скопировать ключ вручную${NC}" fi + else + echo -e "${YELLOW}sshpass не установлен, пропускаю автоматическое копирование${NC}" fi + + # Очистка временного файла + rm -f "$SSH_ASKPASS" + else + echo -e "${YELLOW}Пароль не введен, пропускаю автоматическое копирование ключа${NC}" fi - # Тестовое подключение с улучшенными параметрами - log_message "Тестовое подключение к VPS с новыми настройками..." "$BLUE" + # Альтернативный метод копирования ключа + echo "" + echo -e "${CYAN}Альтернативный способ добавления ключа:${NC}" + echo -e "${YELLOW}Если автоматическое копирование не удалось, выполните следующие шаги:${NC}" + echo "" + echo -e "1. Скопируйте содержимое публичного ключа:" + echo -e "${BOLD}cat /root/.ssh/id_rsa.pub${NC}" + echo "" + echo -e "2. Подключитесь к VPS:" + echo -e "${BOLD}ssh -p $VPS_PORT $VPS_USER@$VPS_HOST${NC}" + echo "" + echo -e "3. На VPS выполните:" + echo -e "${BOLD}mkdir -p ~/.ssh && chmod 700 ~/.ssh${NC}" + echo -e "${BOLD}echo 'ВАШ_ПУБЛИЧНЫЙ_КЛЮЧ' >> ~/.ssh/authorized_keys${NC}" + echo -e "${BOLD}chmod 600 ~/.ssh/authorized_keys${NC}" + echo "" - # Тест с подробным выводом - echo -e "${CYAN}Выполняю тестовое подключение...${NC}" - if ssh -p "$VPS_PORT" \ + safe_read "Нажмите Enter после добавления ключа на VPS..." "" WAIT no + + # Тестовое подключение + log_message "Тестовое подключение к VPS..." "$BLUE" + echo -e "${CYAN}Пытаюсь подключиться без пароля...${NC}" + + if timeout 15 ssh -p "$VPS_PORT" \ -o BatchMode=yes \ - -o ConnectTimeout=15 \ - -o ServerAliveInterval=30 \ - -o TCPKeepAlive=yes \ + -o ConnectTimeout=10 \ + -o StrictHostKeyChecking=no \ "$VPS_USER@$VPS_HOST" \ - "echo 'SSH подключение успешно! Система: \$(uname -a)'"; then + "echo 'SSH подключение успешно!'" 2>&1; then log_message "Тестовое подключение прошло успешно!" "$GREEN" - echo -e "${GREEN}✓ Настройки SSH работают корректно${NC}" + echo -e "${GREEN}✓ SSH ключ настроен корректно${NC}" else log_message "Тестовое подключение не удалось" "$YELLOW" - echo -e "${YELLOW}⚠ SSH подключение не удалось, но установка продолжается${NC}" - echo -e "${YELLOW}Вы сможете настроить подключение позже через tunnel-manager${NC}" - read -p "Продолжить установку? (y/n): " CONTINUE_INSTALL + echo -e "${YELLOW}⚠ Не удалось подключиться без пароля${NC}" + echo -e "${YELLOW}Убедитесь, что ключ добавлен в authorized_keys на VPS${NC}" + + safe_read "Продолжить установку? (y/n): " "y" CONTINUE_INSTALL no + if [[ ! "$CONTINUE_INSTALL" =~ ^[Yy]$ ]]; then exit 1 fi fi # Настройка для не-root пользователей - if [[ $EUID -eq 0 ]] && [ -d "/home/" ]; then + if [[ $EUID -eq 0 ]] && [ -d "/home/" ] && [ "$(ls -A /home/ 2>/dev/null)" ]; then echo "" - read -p "Настроить SSH для обычных пользователей системы? (y/n): " SETUP_USERS + safe_read "Настроить SSH для обычных пользователей системы? (y/n): " "n" SETUP_USERS no if [[ "$SETUP_USERS" =~ ^[Yy]$ ]]; then log_message "Настройка SSH для всех пользователей системы..." "$CYAN" @@ -352,10 +421,11 @@ EOF if [ -f "$USER_SSH_DIR/config" ]; then chown "$USER:$USER" "$USER_SSH_DIR/config" chmod 600 "$USER_SSH_DIR/config" + echo -e " ${GREEN}✓ Конфиг скопирован${NC}" fi - # Копируем ключ если нужно - read -p " Скопировать SSH ключ для пользователя $USER? (y/n): " COPY_FOR_USER + safe_read " Скопировать SSH ключ для пользователя $USER? (y/n): " "n" COPY_FOR_USER no + if [[ "$COPY_FOR_USER" =~ ^[Yy]$ ]]; then cp /root/.ssh/id_rsa* "$USER_SSH_DIR/" 2>/dev/null chown -R "$USER:$USER" "$USER_SSH_DIR" @@ -370,6 +440,8 @@ EOF # Сохранение настроек VPS для использования в скриптах log_message "Сохранение настроек VPS..." "$BLUE" + + mkdir -p /etc/ssh_tunnel cat > /etc/ssh_tunnel/vps_settings.conf << EOF # Настройки VPS для автономных туннелей VPS_HOST="$VPS_HOST" @@ -378,10 +450,11 @@ VPS_USER="$VPS_USER" CONFIGURED_ON="$(date '+%Y-%m-%d %H:%M:%S')" EOF + chmod 600 /etc/ssh_tunnel/vps_settings.conf log_message "Настройки SSH сохранены в /etc/ssh_tunnel/vps_settings.conf" "$GREEN" } -# Установка основного скрипта с полным меню +# Установка основного скрипта управления install_main_script() { log_message "Установка основного скрипта управления туннелями..." "$CYAN" @@ -390,12 +463,17 @@ install_main_script() { mkdir -p /var/log/ssh_tunnel mkdir -p /etc/ssh_tunnel - # Создание основного скрипта с полным меню + # Загрузка настроек VPS если есть + if [ -f /etc/ssh_tunnel/vps_settings.conf ]; then + source /etc/ssh_tunnel/vps_settings.conf + fi + + # Создание основного скрипта менеджера cat > /opt/ssh_tunnel_manager/manager.sh << 'EOF' #!/bin/bash # Основной скрипт менеджера SSH туннелей -# Версия 3.0 - Полное меню управления +# Версия 4.0 - Стабильное меню # Конфигурация CONFIG_DIR="/etc/ssh_tunnel" @@ -413,27 +491,57 @@ PURPLE='\033[0;35m' NC='\033[0m' BOLD='\033[1m' +# Глобальные переменные +VPS_HOST="" +VPS_PORT="22" +VPS_USER="" + # Загрузка настроек VPS если есть -if [ -f "/etc/ssh_tunnel/vps_settings.conf" ]; then - source "/etc/ssh_tunnel/vps_settings.conf" -fi +load_vps_settings() { + if [ -f "/etc/ssh_tunnel/vps_settings.conf" ]; then + source "/etc/ssh_tunnel/vps_settings.conf" + return 0 + fi + return 1 +} + +# Функция безопасного ввода +safe_read() { + local prompt="$1" + local default="$2" + local var_name="$3" + + read -p "$prompt" input + input="${input:-$default}" + + if [ -n "$input" ]; then + eval "$var_name=\"$input\"" + return 0 + else + return 1 + fi +} + +# Очистка входного буфера +clear_input_buffer() { + while read -t 0.1 -n 1000 discard; do :; done +} # Функция проверки подключения check_ssh_connection() { if [ -z "$VPS_HOST" ] || [ -z "$VPS_USER" ]; then echo -e "${RED}Настройки VPS не найдены!${NC}" - echo -e "Запустите установку заново или настройте VPS вручную." return 1 fi - echo -e "${CYAN}Проверка подключения к ${VPS_USER}@${VPS_HOST}:${VPS_PORT:-22}...${NC}" + echo -e "${CYAN}Проверка подключения к ${VPS_USER}@${VPS_HOST}:${VPS_PORT}...${NC}" - if timeout 15 ssh -p "${VPS_PORT:-22}" \ + if timeout 10 ssh -p "$VPS_PORT" \ -o BatchMode=yes \ - -o ConnectTimeout=10 \ - -o ServerAliveInterval=30 \ + -o ConnectTimeout=5 \ + -o StrictHostKeyChecking=no \ "${VPS_USER}@${VPS_HOST}" \ - "echo 'Connected'" 2>/dev/null; then + "echo 'Connected' && exit 0" 2>/dev/null; then echo -e "${GREEN}✓ Подключение успешно${NC}" return 0 else @@ -452,85 +560,44 @@ setup_new_vps() { NEW_VPS_PORT=${NEW_VPS_PORT:-22} read -p "Введите имя пользователя: " NEW_VPS_USER + if [ -z "$NEW_VPS_HOST" ] || [ -z "$NEW_VPS_USER" ]; then + echo -e "${RED}Ошибка: не все поля заполнены${NC}" + return 1 + fi + # Проверка подключения echo -e "${CYAN}Проверка подключения...${NC}" - if timeout 10 ssh -p "$NEW_VPS_PORT" \ - -o ConnectTimeout=5 \ + if timeout 5 ssh -p "$NEW_VPS_PORT" \ + -o ConnectTimeout=3 \ + -o StrictHostKeyChecking=no \ "$NEW_VPS_USER@$NEW_VPS_HOST" \ - "echo 'Проверка успешна'" 2>/dev/null; then + "echo 'OK'" 2>/dev/null; then echo -e "${GREEN}✓ Подключение работает${NC}" - - # Сохранение настроек - cat > /etc/ssh_tunnel/vps_settings.conf << CONFIGEOF + else + echo -e "${YELLOW}⚠ Не удалось проверить подключение${NC}" + read -p "Все равно продолжить? (y/n): " CONTINUE + if [[ ! "$CONTINUE" =~ ^[Yy]$ ]]; then + return 1 + fi + fi + + # Сохранение настроек + cat > /etc/ssh_tunnel/vps_settings.conf << CONFIGEOF # Настройки VPS для автономных туннелей VPS_HOST="$NEW_VPS_HOST" VPS_PORT="$NEW_VPS_PORT" VPS_USER="$NEW_VPS_USER" CONFIGURED_ON="$(date '+%Y-%m-%d %H:%M:%S')" CONFIGEOF - - echo -e "${GREEN}Настройки сохранены!${NC}" - export VPS_HOST="$NEW_VPS_HOST" - export VPS_PORT="$NEW_VPS_PORT" - export VPS_USER="$NEW_VPS_USER" - else - echo -e "${RED}Не удалось подключиться к VPS${NC}" - echo -e "${YELLOW}Проверьте:${NC}" - echo -e "1. Правильность адреса и порта" - echo -e "2. Доступность VPS из сети" - echo -e "3. Наличие SSH ключа в authorized_keys на VPS" - fi + + echo -e "${GREEN}Настройки сохранены!${NC}" + VPS_HOST="$NEW_VPS_HOST" + VPS_PORT="$NEW_VPS_PORT" + VPS_USER="$NEW_VPS_USER" read -p "Нажмите Enter для продолжения..." } -# Функция создания службы -create_service() { - local tunnel_id="$1" - local service_file="/etc/systemd/system/ssh-tunnel-${tunnel_id}.service" - - source "/etc/ssh_tunnel/${tunnel_id}.conf" - - cat > "$service_file" << SERVICEEOF -[Unit] -Description=SSH Tunnel: $tunnel_id -After=network-online.target -Wants=network-online.target - -[Service] -Type=simple -EnvironmentFile=/etc/ssh_tunnel/${tunnel_id}.conf -ExecStart=/usr/bin/autossh -M 0 -N \\ - -o "ExitOnForwardFailure=yes" \\ - -o "ServerAliveInterval=30" \\ - -o "ServerAliveCountMax=3" \\ - -o "StrictHostKeyChecking=no" \\ - -o "UserKnownHostsFile=/dev/null" \\ - -o "TCPKeepAlive=yes" \\ - -o "ConnectTimeout=30" \\ - -R \${REMOTE_PORT}:localhost:\${LOCAL_PORT} \\ - \${VPS_USER}@\${VPS_HOST} -p \${VPS_PORT} -Restart=always -RestartSec=10 -User=root - -StandardOutput=append:/var/log/ssh_tunnel/${tunnel_id}.log -StandardError=append:/var/log/ssh_tunnel/${tunnel_id}.log - -[Install] -WantedBy=multi-user.target -SERVICEEOF - - systemctl daemon-reload - systemctl enable "ssh-tunnel-${tunnel_id}.service" - systemctl start "ssh-tunnel-${tunnel_id}.service" - - echo -e "${GREEN}Служба создана и запущена!${NC}" - echo -e "${CYAN}Управление:${NC}" - echo -e " sudo systemctl status ssh-tunnel-${tunnel_id}.service" - echo -e " sudo systemctl restart ssh-tunnel-${tunnel_id}.service" -} - # Создание туннеля create_tunnel() { echo -e "${CYAN}Создание нового туннеля...${NC}" @@ -544,11 +611,18 @@ create_tunnel() { read -p "Введите локальный порт (например 22): " LOCAL_PORT read -p "Введите удаленный порт на VPS (например 10022): " REMOTE_PORT + if [ -z "$LOCAL_PORT" ] || [ -z "$REMOTE_PORT" ]; then + echo -e "${RED}Ошибка: не все поля заполнены${NC}" + return + fi + echo -e "${CYAN}Создание туннеля $LOCAL_PORT -> $REMOTE_PORT на ${VPS_HOST}...${NC}" # Создание конфигурации TUNNEL_ID="tunnel_${REMOTE_PORT}_$(date +%s)" - cat > "/etc/ssh_tunnel/${TUNNEL_ID}.conf" << EOF + CONFIG_FILE="/etc/ssh_tunnel/${TUNNEL_ID}.conf" + + cat > "$CONFIG_FILE" << EOF TUNNEL_ID="$TUNNEL_ID" VPS_HOST="$VPS_HOST" VPS_PORT="$VPS_PORT" @@ -558,10 +632,48 @@ REMOTE_PORT="$REMOTE_PORT" CREATED="$(date '+%Y-%m-%d %H:%M:%S')" EOF - echo -e "${GREEN}Туннель создан! Конфиг: /etc/ssh_tunnel/${TUNNEL_ID}.conf${NC}" + echo -e "${GREEN}Туннель создан! Конфиг: $CONFIG_FILE${NC}" # Создание службы - create_service "$TUNNEL_ID" + SERVICE_FILE="/etc/systemd/system/ssh-tunnel-${TUNNEL_ID}.service" + + cat > "$SERVICE_FILE" << SERVICEEOF +[Unit] +Description=SSH Tunnel: $TUNNEL_ID +After=network-online.target +Wants=network-online.target + +[Service] +Type=simple +EnvironmentFile=$CONFIG_FILE +ExecStart=/usr/bin/autossh -M 0 -N \\ + -o "ExitOnForwardFailure=yes" \\ + -o "ServerAliveInterval=30" \\ + -o "ServerAliveCountMax=3" \\ + -o "StrictHostKeyChecking=no" \\ + -o "UserKnownHostsFile=/dev/null" \\ + -o "TCPKeepAlive=yes" \\ + -o "ConnectTimeout=30" \\ + -R \${REMOTE_PORT}:localhost:\${LOCAL_PORT} \\ + \${VPS_USER}@\${VPS_HOST} -p \${VPS_PORT} +Restart=always +RestartSec=10 +User=root + +StandardOutput=append:/var/log/ssh_tunnel/${TUNNEL_ID}.log +StandardError=append:/var/log/ssh_tunnel/${TUNNEL_ID}.log + +[Install] +WantedBy=multi-user.target +SERVICEEOF + + systemctl daemon-reload + systemctl enable "ssh-tunnel-${TUNNEL_ID}.service" 2>/dev/null + systemctl start "ssh-tunnel-${TUNNEL_ID}.service" 2>/dev/null + + echo -e "${GREEN}Служба создана и запущена!${NC}" + echo -e "${CYAN}Для подключения используйте:${NC}" + echo -e "${BOLD}ssh -p $REMOTE_PORT ${VPS_USER}@${VPS_HOST}${NC}" read -p "Нажмите Enter для продолжения..." } @@ -576,13 +688,15 @@ quick_ssh_tunnel() { return fi - REMOTE_PORT="10022" LOCAL_PORT="22" + REMOTE_PORT="10022" echo -e "${YELLOW}Будет создан туннель: localhost:22 -> ${VPS_HOST}:${REMOTE_PORT}${NC}" TUNNEL_ID="ssh_tunnel_${REMOTE_PORT}" - cat > "/etc/ssh_tunnel/${TUNNEL_ID}.conf" << EOF + CONFIG_FILE="/etc/ssh_tunnel/${TUNNEL_ID}.conf" + + cat > "$CONFIG_FILE" << EOF TUNNEL_ID="$TUNNEL_ID" VPS_HOST="$VPS_HOST" VPS_PORT="$VPS_PORT" @@ -593,12 +707,46 @@ CREATED="$(date '+%Y-%m-%d %H:%M:%S')" TYPE="ssh" EOF + SERVICE_FILE="/etc/systemd/system/ssh-tunnel-${TUNNEL_ID}.service" + + cat > "$SERVICE_FILE" << SERVICEEOF +[Unit] +Description=SSH Tunnel: $TUNNEL_ID +After=network-online.target +Wants=network-online.target + +[Service] +Type=simple +EnvironmentFile=$CONFIG_FILE +ExecStart=/usr/bin/autossh -M 0 -N \\ + -o "ExitOnForwardFailure=yes" \\ + -o "ServerAliveInterval=30" \\ + -o "ServerAliveCountMax=3" \\ + -o "StrictHostKeyChecking=no" \\ + -o "UserKnownHostsFile=/dev/null" \\ + -o "TCPKeepAlive=yes" \\ + -o "ConnectTimeout=30" \\ + -R \${REMOTE_PORT}:localhost:\${LOCAL_PORT} \\ + \${VPS_USER}@\${VPS_HOST} -p \${VPS_PORT} +Restart=always +RestartSec=10 +User=root + +StandardOutput=append:/var/log/ssh_tunnel/${TUNNEL_ID}.log +StandardError=append:/var/log/ssh_tunnel/${TUNNEL_ID}.log + +[Install] +WantedBy=multi-user.target +SERVICEEOF + + systemctl daemon-reload + systemctl enable "ssh-tunnel-${TUNNEL_ID}.service" 2>/dev/null + systemctl start "ssh-tunnel-${TUNNEL_ID}.service" 2>/dev/null + echo -e "${GREEN}SSH туннель создан!${NC}" echo -e "${CYAN}Для подключения используйте:${NC}" echo -e "${BOLD}ssh -p $REMOTE_PORT ${VPS_USER}@${VPS_HOST}${NC}" - create_service "$TUNNEL_ID" - read -p "Нажмите Enter для продолжения..." } @@ -611,19 +759,19 @@ manage_tunnels() { echo "" # Список туннелей - count=1 + count=0 declare -A tunnels - for conf in /etc/ssh_tunnel/*.conf; do + for conf in /etc/ssh_tunnel/*.conf 2>/dev/null; do if [ -f "$conf" ]; then + ((count++)) tunnels[$count]="$conf" tunnel_name=$(basename "$conf" .conf) echo -e "${CYAN}[$count]${NC} $tunnel_name" - ((count++)) fi done - if [ $count -eq 1 ]; then + if [ $count -eq 0 ]; then echo -e "${YELLOW}Нет настроенных туннелей${NC}" fi @@ -633,18 +781,19 @@ manage_tunnels() { echo -e "${CYAN}[b]${NC} Назад в главное меню" echo "" - read -p "Выберите туннель для управления или действие: " choice + clear_input_buffer + read -p "Выберите опцию: " choice case $choice in b|B) return ;; s|S) echo -e "${CYAN}Статус туннелей:${NC}" - systemctl list-units --type=service --state=running | grep ssh-tunnel + systemctl list-units --type=service --state=active | grep ssh-tunnel || echo "Нет активных туннелей" read -p "Нажмите Enter для продолжения..." ;; r|R) echo -e "${CYAN}Перезапуск всех туннелей...${NC}" - for conf in /etc/ssh_tunnel/*.conf; do + for conf in /etc/ssh_tunnel/*.conf 2>/dev/null; do if [ -f "$conf" ]; then tunnel_name=$(basename "$conf" .conf) systemctl restart "ssh-tunnel-${tunnel_name}.service" 2>/dev/null @@ -654,7 +803,7 @@ manage_tunnels() { read -p "Нажмите Enter для продолжения..." ;; *) - if [[ $choice =~ ^[0-9]+$ ]] && [ $choice -ge 1 ] && [ $choice -lt $count ]; then + if [[ $choice =~ ^[0-9]+$ ]] && [ $choice -ge 1 ] && [ $choice -le $count ]; then manage_single_tunnel "${tunnels[$choice]}" else echo -e "${RED}Неверный выбор${NC}" @@ -670,7 +819,10 @@ manage_single_tunnel() { local conf="$1" local tunnel_name=$(basename "$conf" .conf) - source "$conf" + source "$conf" 2>/dev/null || { + echo -e "${RED}Ошибка загрузки конфигурации${NC}" + return + } while true; do clear @@ -678,13 +830,13 @@ manage_single_tunnel() { echo -e "${YELLOW}=================================${NC}" echo "" echo -e "${CYAN}Информация:${NC}" - echo -e " Локальный порт: $LOCAL_PORT" - echo -e " Удаленный порт: $REMOTE_PORT" - echo -e " VPS: $VPS_USER@$VPS_HOST:$VPS_PORT" + echo -e " Локальный порт: ${LOCAL_PORT:-не указан}" + echo -e " Удаленный порт: ${REMOTE_PORT:-не указан}" + echo -e " VPS: ${VPS_USER:-не указан}@${VPS_HOST:-не указан}:${VPS_PORT:-22}" echo "" # Проверка статуса - if systemctl is-active --quiet "ssh-tunnel-${tunnel_name}.service"; then + if systemctl is-active --quiet "ssh-tunnel-${tunnel_name}.service" 2>/dev/null; then echo -e "${GREEN}✓ Служба активна${NC}" else echo -e "${RED}✗ Служба неактивна${NC}" @@ -699,21 +851,22 @@ manage_single_tunnel() { echo -e "${CYAN}[6]${NC} Назад" echo "" + clear_input_buffer read -p "Выберите действие: " action case $action in 1) - systemctl restart "ssh-tunnel-${tunnel_name}.service" + systemctl restart "ssh-tunnel-${tunnel_name}.service" 2>/dev/null echo -e "${GREEN}Туннель перезапущен${NC}" sleep 1 ;; 2) - systemctl stop "ssh-tunnel-${tunnel_name}.service" + systemctl stop "ssh-tunnel-${tunnel_name}.service" 2>/dev/null echo -e "${YELLOW}Туннель остановлен${NC}" sleep 1 ;; 3) - systemctl start "ssh-tunnel-${tunnel_name}.service" + systemctl start "ssh-tunnel-${tunnel_name}.service" 2>/dev/null echo -e "${GREEN}Туннель запущен${NC}" sleep 1 ;; @@ -725,11 +878,11 @@ manage_single_tunnel() { 5) read -p "Вы уверены, что хотите удалить туннель $tunnel_name? (y/n): " confirm if [[ "$confirm" =~ ^[Yy]$ ]]; then - systemctl stop "ssh-tunnel-${tunnel_name}.service" - systemctl disable "ssh-tunnel-${tunnel_name}.service" + systemctl stop "ssh-tunnel-${tunnel_name}.service" 2>/dev/null + systemctl disable "ssh-tunnel-${tunnel_name}.service" 2>/dev/null rm -f "/etc/systemd/system/ssh-tunnel-${tunnel_name}.service" rm -f "$conf" - rm -f "/var/log/ssh_tunnel/${tunnel_name}.log" + rm -f "/var/log/ssh_tunnel/${tunnel_name}.log" 2>/dev/null systemctl daemon-reload echo -e "${GREEN}Туннель удален${NC}" return @@ -748,60 +901,57 @@ manage_single_tunnel() { # Настройка автозапуска setup_autostart() { - echo -e "${CYAN}Настройка автозапуска...${NC}" - - echo "1) Включить автозапуск всех туннелей" - echo "2) Выключить автозапуск всех туннелей" - echo "3) Настроить отдельную службу" - echo "4) Проверить статус автозапуска" - echo "5) Назад" - - read -p "Выберите действие [1-5]: " action - - case $action in - 1) - for conf in /etc/ssh_tunnel/*.conf; do - if [ -f "$conf" ]; then - tunnel_name=$(basename "$conf" .conf) - systemctl enable "ssh-tunnel-${tunnel_name}.service" 2>/dev/null - echo -e "${GREEN}✓ Автозапуск включен для $tunnel_name${NC}" - fi - done - ;; - 2) - for conf in /etc/ssh_tunnel/*.conf; do - if [ -f "$conf" ]; then - tunnel_name=$(basename "$conf" .conf) - systemctl disable "ssh-tunnel-${tunnel_name}.service" 2>/dev/null - echo -e "${YELLOW}✗ Автозапуск выключен для $tunnel_name${NC}" - fi - done - ;; - 3) - echo -e "${CYAN}Доступные службы:${NC}" - systemctl list-unit-files --type=service | grep ssh-tunnel - read -p "Введите имя службы: " service_name - if systemctl is-enabled "$service_name" 2>/dev/null; then - systemctl disable "$service_name" - echo -e "${YELLOW}Автозапуск выключен для $service_name${NC}" - else - systemctl enable "$service_name" - echo -e "${GREEN}Автозапуск включен для $service_name${NC}" - fi - ;; - 4) - echo -e "${CYAN}Статус автозапуска:${NC}" - systemctl list-unit-files --type=service | grep ssh-tunnel - ;; - 5) - return - ;; - *) - echo -e "${RED}Неверный выбор${NC}" - ;; - esac - - read -p "Нажмите Enter для продолжения..." + while true; do + clear + echo -e "${BOLD}${CYAN}Настройка автозапуска${NC}" + echo -e "${YELLOW}======================${NC}" + echo "" + echo -e "${CYAN}[1]${NC} Включить автозапуск всех туннелей" + echo -e "${CYAN}[2]${NC} Выключить автозапуск всех туннелей" + echo -e "${CYAN}[3]${NC} Проверить статус автозапуска" + echo -e "${CYAN}[4]${NC} Назад" + echo "" + + clear_input_buffer + read -p "Выберите действие: " action + + case $action in + 1) + for conf in /etc/ssh_tunnel/*.conf 2>/dev/null; do + if [ -f "$conf" ]; then + tunnel_name=$(basename "$conf" .conf) + systemctl enable "ssh-tunnel-${tunnel_name}.service" 2>/dev/null && \ + echo -e "${GREEN}✓ Автозапуск включен для $tunnel_name${NC}" || \ + echo -e "${RED}✗ Ошибка для $tunnel_name${NC}" + fi + done + read -p "Нажмите Enter для продолжения..." + ;; + 2) + for conf in /etc/ssh_tunnel/*.conf 2>/dev/null; do + if [ -f "$conf" ]; then + tunnel_name=$(basename "$conf" .conf) + systemctl disable "ssh-tunnel-${tunnel_name}.service" 2>/dev/null && \ + echo -e "${YELLOW}✗ Автозапуск выключен для $tunnel_name${NC}" || \ + echo -e "${RED}✗ Ошибка для $tunnel_name${NC}" + fi + done + read -p "Нажмите Enter для продолжения..." + ;; + 3) + echo -e "${CYAN}Статус автозапуска:${NC}" + systemctl list-unit-files --type=service | grep ssh-tunnel || echo "Нет служб туннелей" + read -p "Нажмите Enter для продолжения..." + ;; + 4) + return + ;; + *) + echo -e "${RED}Неверный выбор${NC}" + sleep 1 + ;; + esac + done } # Просмотр логов @@ -813,20 +963,22 @@ view_logs() { echo "" echo -e "${CYAN}[1]${NC} Логи конкретного туннеля" echo -e "${CYAN}[2]${NC} Все логи туннелей" - echo -e "${CYAN}[3]${NC} Системные логи (journalctl)" + echo -e "${CYAN}[3]${NC} Системные логи" echo -e "${CYAN}[4]${NC} Лог монитора" - echo -e "${CYAN}[5]${NC} Реальный мониторинг (tail -f)" - echo -e "${CYAN}[6]${NC} Очистить все логи" - echo -e "${CYAN}[7]${NC} Назад" + echo -e "${CYAN}[5]${NC} Реальный мониторинг" + echo -e "${CYAN}[6]${NC} Назад" echo "" - read -p "Выберите действие [1-7]: " choice + clear_input_buffer + read -p "Выберите действие: " choice case $choice in 1) + echo -e "${CYAN}Доступные логи:${NC}" ls $LOG_DIR/*.log 2>/dev/null | while read log; do echo " $(basename $log)" done + echo "" read -p "Введите имя лог-файла: " log_file if [ -f "$LOG_DIR/$log_file" ]; then less "$LOG_DIR/$log_file" @@ -837,17 +989,17 @@ view_logs() { ;; 2) echo -e "${CYAN}Все логи туннелей:${NC}" - for log in $LOG_DIR/*.log; do + for log in $LOG_DIR/*.log 2>/dev/null; do if [ -f "$log" ]; then echo -e "\n${YELLOW}=== $(basename $log) ===${NC}" - tail -10 "$log" + tail -5 "$log" fi done read -p "Нажмите Enter для продолжения..." ;; 3) echo -e "${CYAN}Системные логи туннелей:${NC}" - journalctl -u ssh-tunnel-* --since "1 hour ago" -n 20 + journalctl -u ssh-tunnel-* --since "1 hour ago" -n 10 2>/dev/null || echo "Логи отсутствуют" read -p "Нажмите Enter для продолжения..." ;; 4) @@ -861,17 +1013,10 @@ view_logs() { ;; 5) echo -e "${CYAN}Реальный мониторинг логов (Ctrl+C для выхода)${NC}" - tail -f $LOG_DIR/*.log 2>/dev/null | grep --line-buffered -E "ERROR|FAIL|Active|Inactive|restart|connected|disconnected" + trap 'echo -e "\n${YELLOW}Мониторинг остановлен${NC}"' INT + tail -f $LOG_DIR/*.log 2>/dev/null ;; 6) - read -p "Вы уверены, что хотите очистить все логи? (y/n): " confirm - if [[ "$confirm" =~ ^[Yy]$ ]]; then - rm -f $LOG_DIR/*.log 2>/dev/null - echo -e "${GREEN}Логи очищены${NC}" - sleep 1 - fi - ;; - 7) return ;; *) @@ -888,10 +1033,10 @@ test_connections() { echo "1) Тест подключения к VPS" echo "2) Тест портов туннелей" - echo "3) Тест скорости соединения" - echo "4) Назад" + echo "3) Назад" - read -p "Выберите тест [1-4]: " test_choice + clear_input_buffer + read -p "Выберите тест: " test_choice case $test_choice in 1) @@ -899,9 +1044,9 @@ test_connections() { ;; 2) echo -e "${CYAN}Тест портов туннелей:${NC}" - for conf in /etc/ssh_tunnel/*.conf; do + for conf in /etc/ssh_tunnel/*.conf 2>/dev/null; do if [ -f "$conf" ]; then - source "$conf" + source "$conf" 2>/dev/null tunnel_name=$(basename "$conf" .conf) echo -n " $tunnel_name (локальный $LOCAL_PORT): " if timeout 2 nc -z localhost "$LOCAL_PORT" 2>/dev/null; then @@ -913,19 +1058,11 @@ test_connections() { done ;; 3) - if [ -n "$VPS_HOST" ]; then - echo -e "${CYAN}Тест скорости соединения с VPS...${NC}" - timeout 10 ssh "$VPS_USER@$VPS_HOST" "dd if=/dev/zero bs=1M count=10 2>/dev/null | gzip -f | dd of=/dev/null 2>/dev/null" 2>/dev/null - if [ $? -eq 0 ]; then - echo -e "${GREEN}✓ Соединение стабильное${NC}" - else - echo -e "${YELLOW}⚠ Соединение медленное или нестабильное${NC}" - fi - fi - ;; - 4) return ;; + *) + echo -e "${RED}Неверный выбор${NC}" + ;; esac read -p "Нажмите Enter для продолжения..." @@ -937,43 +1074,46 @@ setup_routing() { echo "1) Показать текущие правила iptables" echo "2) Добавить правило перенаправления порта" - echo "3) Удалить правило" - echo "4) Сохранить правила" - echo "5) Назад" + echo "3) Сохранить правила" + echo "4) Назад" - read -p "Выберите действие [1-5]: " routing_choice + clear_input_buffer + read -p "Выберите действие: " routing_choice case $routing_choice in 1) echo -e "${CYAN}Текущие правила iptables:${NC}" - iptables -t nat -L -n -v + iptables -t nat -L -n -v 2>/dev/null || echo "iptables не установлен" ;; 2) read -p "Входной порт: " in_port read -p "IP назначения: " dest_ip read -p "Порт назначения: " dest_port - iptables -t nat -A PREROUTING -p tcp --dport "$in_port" -j DNAT --to-destination "$dest_ip:$dest_port" - iptables -t nat -A POSTROUTING -p tcp -d "$dest_ip" --dport "$dest_port" -j MASQUERADE - - echo -e "${GREEN}Правило добавлено${NC}" + if [ -n "$in_port" ] && [ -n "$dest_ip" ] && [ -n "$dest_port" ]; then + iptables -t nat -A PREROUTING -p tcp --dport "$in_port" -j DNAT --to-destination "$dest_ip:$dest_port" 2>/dev/null + iptables -t nat -A POSTROUTING -p tcp -d "$dest_ip" --dport "$dest_port" -j MASQUERADE 2>/dev/null + echo -e "${GREEN}Правило добавлено${NC}" + else + echo -e "${RED}Не все поля заполнены${NC}" + fi ;; 3) - read -p "Входной порт для удаления: " del_port - iptables -t nat -D PREROUTING -p tcp --dport "$del_port" -j DNAT 2>/dev/null - echo -e "${YELLOW}Правило удалено (если существовало)${NC}" - ;; - 4) if command -v iptables-save &> /dev/null; then - iptables-save > /etc/iptables/rules.v4 - echo -e "${GREEN}Правила сохранены${NC}" + mkdir -p /etc/iptables + iptables-save > /etc/iptables/rules.v4 2>/dev/null && \ + echo -e "${GREEN}Правила сохранены${NC}" || \ + echo -e "${RED}Ошибка сохранения${NC}" else echo -e "${RED}iptables-save не найден${NC}" fi ;; - 5) + 4) return ;; + *) + echo -e "${RED}Неверный выбор${NC}" + ;; esac read -p "Нажмите Enter для продолжения..." @@ -988,7 +1128,8 @@ setup_ssh_config() { echo "3) Проверить конфигурацию" echo "4) Назад" - read -p "Выберите действие [1-4]: " ssh_choice + clear_input_buffer + read -p "Выберите действие: " ssh_choice case $ssh_choice in 1) @@ -996,8 +1137,11 @@ setup_ssh_config() { grep -E "^(ClientAlive|TCPKeepAlive|ServerAlive|Port|PasswordAuthentication|PermitRootLogin)" /etc/ssh/sshd_config 2>/dev/null || echo "Конфигурация не найдена" ;; 2) - systemctl restart sshd 2>/dev/null || service ssh restart 2>/dev/null - echo -e "${GREEN}SSH демон перезапущен${NC}" + if systemctl restart sshd 2>/dev/null || service ssh restart 2>/dev/null; then + echo -e "${GREEN}SSH демон перезапущен${NC}" + else + echo -e "${RED}Ошибка перезапуска SSH демона${NC}" + fi ;; 3) if sshd -t 2>/dev/null; then @@ -1009,6 +1153,9 @@ setup_ssh_config() { 4) return ;; + *) + echo -e "${RED}Неверный выбор${NC}" + ;; esac read -p "Нажмите Enter для продолжения..." @@ -1016,15 +1163,18 @@ setup_ssh_config() { # Основное меню show_menu() { + # Загрузка настроек + load_vps_settings + while true; do clear echo -e "${BOLD}${CYAN}════════════════════════════════════════════════════════════════${NC}" - echo -e "${BOLD}${CYAN} АВТОНОМНЫЙ МЕНЕДЖЕР SSH ТУННЕЛЕЙ v3.0 ${NC}" + echo -e "${BOLD}${CYAN} АВТОНОМНЫЙ МЕНЕДЖЕР SSH ТУННЕЛЕЙ v4.0 ${NC}" echo -e "${BOLD}${CYAN}════════════════════════════════════════════════════════════════${NC}" # Отображение текущих настроек VPS if [ -n "$VPS_HOST" ]; then - echo -e "${CYAN}Текущий VPS: ${VPS_USER}@${VPS_HOST}:${VPS_PORT:-22}${NC}" + echo -e "${CYAN}Текущий VPS: ${VPS_USER}@${VPS_HOST}:${VPS_PORT}${NC}" else echo -e "${RED}VPS не настроен! Выберите опцию 9 для настройки.${NC}" fi @@ -1033,7 +1183,7 @@ show_menu() { # Проверка статуса подключения if [ -n "$VPS_HOST" ]; then - echo -e "${CYAN}Проверка состояния подключения...${NC}" + echo -e "${CYAN}Статус подключения:${NC}" if check_ssh_connection; then echo -e "${GREEN}✓ Соединение с VPS активно${NC}" else @@ -1048,11 +1198,13 @@ show_menu() { echo -e "${BOLD}${YELLOW}[4]${NC} Настройка автозапуска" echo -e "${BOLD}${YELLOW}[5]${NC} Просмотр логов и мониторинг" echo -e "${BOLD}${YELLOW}[6]${NC} Тестирование подключений" - echo -e "${BOLD}${YELLow}[7]${NC} Настройка маршрутизации" + echo -e "${BOLD}${YELLOW}[7]${NC} Настройка маршрутизации" echo -e "${BOLD}${YELLOW}[8]${NC} Настройки SSH" echo -e "${BOLD}${YELLOW}[9]${NC} Настройка/смена VPS" echo -e "${BOLD}${YELLOW}[0]${NC} Выход" echo "" + + clear_input_buffer read -p "Выберите опцию [0-9]: " choice case $choice in @@ -1070,7 +1222,7 @@ show_menu() { exit 0 ;; *) - echo -e "${RED}Неверный выбор${NC}" + echo -e "${RED}Неверный выбор. Попробуйте еще раз.${NC}" sleep 1 ;; esac @@ -1078,7 +1230,9 @@ show_menu() { } # Главный цикл -show_menu +if [ "$0" = "$BASH_SOURCE" ] || [ "$0" = "./manager.sh" ]; then + show_menu +fi EOF # Создание файла с цветами @@ -1211,12 +1365,12 @@ EOF # Включение служб systemctl daemon-reload - systemctl enable tunnel-monitor.service - systemctl enable tunnel-check.timer - systemctl start tunnel-monitor.service - systemctl start tunnel-check.timer + systemctl enable tunnel-monitor.service 2>/dev/null + systemctl enable tunnel-check.timer 2>/dev/null + systemctl start tunnel-monitor.service 2>/dev/null + systemctl start tunnel-check.timer 2>/dev/null - log_message "Systemd службы настроены и запущены" "$GREEN" + log_message "Systemd службы настроены" "$GREEN" } # Создание примера туннеля @@ -1224,7 +1378,7 @@ create_example_tunnel() { log_message "Создание примера SSH туннеля..." "$CYAN" if [ -n "$VPS_HOST" ] && [ -n "$VPS_USER" ]; then - read -p "Создать пример туннеля для SSH (порт 22 -> 10022)? (y/n): " CREATE_EXAMPLE + safe_read "Создать пример туннеля для SSH (порт 22 -> 10022)? (y/n): " "y" CREATE_EXAMPLE no if [[ "$CREATE_EXAMPLE" =~ ^[Yy]$ ]]; then cat > /etc/ssh_tunnel/example_ssh.conf << EOF @@ -1247,15 +1401,15 @@ After=network-online.target [Service] Type=simple EnvironmentFile=/etc/ssh_tunnel/example_ssh.conf -ExecStart=/usr/bin/autossh -M 0 -N \ - -o "ExitOnForwardFailure=yes" \ - -o "ServerAliveInterval=30" \ - -o "ServerAliveCountMax=3" \ - -o "StrictHostKeyChecking=no" \ - -o "UserKnownHostsFile=/dev/null" \ - -o "TCPKeepAlive=yes" \ - -o "ConnectTimeout=30" \ - -R \${REMOTE_PORT}:localhost:\${LOCAL_PORT} \ +ExecStart=/usr/bin/autossh -M 0 -N \\ + -o "ExitOnForwardFailure=yes" \\ + -o "ServerAliveInterval=30" \\ + -o "ServerAliveCountMax=3" \\ + -o "StrictHostKeyChecking=no" \\ + -o "UserKnownHostsFile=/dev/null" \\ + -o "TCPKeepAlive=yes" \\ + -o "ConnectTimeout=30" \\ + -R \${REMOTE_PORT}:localhost:\${LOCAL_PORT} \\ \${VPS_USER}@\${VPS_HOST} -p \${VPS_PORT} Restart=always RestartSec=10 @@ -1269,10 +1423,11 @@ WantedBy=multi-user.target EOF systemctl daemon-reload - systemctl enable ssh-tunnel-example_ssh.service - systemctl start ssh-tunnel-example_ssh.service + systemctl enable ssh-tunnel-example_ssh.service 2>/dev/null + systemctl start ssh-tunnel-example_ssh.service 2>/dev/null - log_message "Пример туннеля создан! Для подключения используйте:" "$GREEN" + log_message "Пример туннеля создан!" "$GREEN" + echo -e "${CYAN}Для подключения используйте:${NC}" echo -e "${BOLD}ssh -p 10022 $VPS_USER@$VPS_HOST${NC}" echo "" echo -e "${YELLOW}Проверьте подключение:${NC}" @@ -1294,7 +1449,7 @@ finish_installation() { echo -e "${GREEN}✓${NC} Зависимости установлены" echo -e "${GREEN}✓${NC} SSH ключи сгенерированы и настроены" echo -e "${GREEN}✓${NC} SSH конфигурация улучшена для стабильности" - echo -e "${GREEN}✓${NC} Основной скрипт установлен: /opt/ssh_tunnel_manager/manager.sh" + echo -e "${GREEN}✓${NC} Основной скрипт установлен" echo -e "${GREEN}✓${NC} Systemd службы настроены" echo -e "${GREEN}✓${NC} Автозапуск включен" echo "" @@ -1311,8 +1466,8 @@ finish_installation() { echo -e " ${CYAN}tunnel-manager${NC} - запуск менеджера туннелей" echo -e " ${CYAN}systemctl status tunnel-monitor${NC} - статус монитора" echo -e " ${CYAN}journalctl -u tunnel-monitor -f${NC} - просмотр логов" - echo -e " ${CYAN}ssh -p ${VPS_PORT:-22} $VPS_USER@$VPS_HOST${NC} - тестовое подключение" echo "" + echo -e "${BOLD}Автономная работа гарантирована!${NC}" echo -e "Система автоматически запустится после перезагрузки." echo "" @@ -1320,7 +1475,8 @@ finish_installation() { echo "" # Запрос на перезагрузку - read -p "Перезагрузить систему для применения всех настроек? (y/n): " REBOOT_NOW + safe_read "Перезагрузить систему для применения всех настроек? (y/n): " "n" REBOOT_NOW no + if [[ "$REBOOT_NOW" =~ ^[Yy]$ ]]; then log_message "Перезагрузка системы по запросу пользователя..." "$YELLOW" echo -e "${YELLOW}Система перезагрузится через 5 секунд...${NC}"