Исправления в этой версии:
Исправлены все ошибки с EOF - использованы разные метки для вложенных EOF (EOFMGR, EOFCOLORS, EOFSERVICE, EOFMONITOR, EOFTIMER, EOFEXAMPLE, EOFEXSERVICE)
Убраны конфликтующие метки - каждая вложенная конструкция << имеет уникальную метку
Исправлена проблема с созданием файлов - все файлы создаются корректно, включая /opt/ssh_tunnel_manager/colors.sh
Убраны синтаксические ошибки - скрипт теперь компилируется без ошибок
Добавлена проверка на существование директорий перед созданием файлов
1530 lines
58 KiB
Bash
1530 lines
58 KiB
Bash
#!/bin/bash
|
||
|
||
# Установщик автономного менеджера SSH туннелей
|
||
# Использование: bash <(curl -s https://git.softuniq.eu/OpenDoor/vps_ssh_tunel/raw/branch/main/install_ssh_tunnel.sh)
|
||
|
||
# Цвета для вывода
|
||
RED='\033[0;31m'
|
||
GREEN='\033[0;32m'
|
||
YELLOW='\033[1;33m'
|
||
BLUE='\033[0;34m'
|
||
CYAN='\033[0;36m'
|
||
NC='\033[0m'
|
||
BOLD='\033[1m'
|
||
|
||
# Логирование
|
||
LOG_FILE="/tmp/ssh_tunnel_install.log"
|
||
|
||
log_message() {
|
||
echo -e "${2:-$NC}[$(date '+%Y-%m-%d %H:%M:%S')] $1${NC}" | tee -a "$LOG_FILE"
|
||
}
|
||
|
||
clear
|
||
echo -e "${BOLD}${CYAN}════════════════════════════════════════════════════════════════${NC}"
|
||
echo -e "${BOLD}${CYAN} УСТАНОВКА АВТОНОМНОГО МЕНЕДЖЕРА SSH ТУННЕЛЕЙ ${NC}"
|
||
echo -e "${BOLD}${CYAN}════════════════════════════════════════════════════════════════${NC}"
|
||
echo ""
|
||
|
||
# Проверка прав root
|
||
if [[ $EUID -ne 0 ]]; then
|
||
echo -e "${RED}ОШИБКА: Этот скрипт требует прав root (sudo).${NC}"
|
||
echo "Пожалуйста, запустите снова:"
|
||
echo -e "${BOLD}sudo bash <(curl -s https://git.softuniq.eu/OpenDoor/vps_ssh_tunel/raw/branch/main/install_ssh_tunnel.sh)${NC}"
|
||
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"
|
||
return 1
|
||
fi
|
||
return 0
|
||
}
|
||
|
||
# Определение дистрибутива
|
||
detect_distro() {
|
||
log_message "Определение операционной системы..." "$CYAN"
|
||
|
||
if [ -f /etc/os-release ]; then
|
||
. /etc/os-release
|
||
OS=$ID
|
||
VERSION=$VERSION_ID
|
||
elif [ -f /etc/redhat-release ]; then
|
||
OS="rhel"
|
||
VERSION=$(cat /etc/redhat-release | sed 's/.*release \([0-9]\).*/\1/')
|
||
else
|
||
OS=$(uname -s)
|
||
VERSION=$(uname -r)
|
||
fi
|
||
|
||
log_message "Система: $OS $VERSION" "$GREEN"
|
||
}
|
||
|
||
# Установка зависимостей
|
||
install_dependencies() {
|
||
log_message "Установка необходимых зависимостей..." "$CYAN"
|
||
|
||
case $OS in
|
||
ubuntu|debian)
|
||
log_message "Обновление списка пакетов..." "$BLUE"
|
||
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 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 sshpass 2>&1 | tee -a "$LOG_FILE"
|
||
else
|
||
yum install -y autossh openssh-clients net-tools curl git sshpass 2>&1 | tee -a "$LOG_FILE"
|
||
fi
|
||
check_error "Не удалось установить пакеты"
|
||
;;
|
||
|
||
*)
|
||
log_message "Неизвестный дистрибутив. Попытка установки вручную..." "$YELLOW"
|
||
# Попытка установить 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 ..
|
||
fi
|
||
;;
|
||
esac
|
||
|
||
log_message "Зависимости успешно установлены!" "$GREEN"
|
||
}
|
||
|
||
# Настройка SSH
|
||
setup_ssh() {
|
||
log_message "Настройка SSH системы..." "$CYAN"
|
||
|
||
# Создание директорий SSH если их нет
|
||
mkdir -p /root/.ssh
|
||
chmod 700 /root/.ssh
|
||
|
||
# Запрос данных VPS
|
||
echo ""
|
||
echo -e "${BOLD}${YELLOW}════════════════════════════════════════════════════════════════${NC}"
|
||
echo -e "${BOLD}${YELLOW} НАСТРОЙКА ПОДКЛЮЧЕНИЯ К VPS ${NC}"
|
||
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
|
||
|
||
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 "${YELLOW}Повторите ввод данных...${NC}"
|
||
echo ""
|
||
fi
|
||
done
|
||
|
||
# Проверка подключения
|
||
log_message "Проверка подключения к $VPS_USER@$VPS_HOST:$VPS_PORT..." "$BLUE"
|
||
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"
|
||
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
|
||
fi
|
||
|
||
# Генерация SSH ключа
|
||
echo ""
|
||
log_message "Генерация SSH ключа RSA 4096 бит..." "$CYAN"
|
||
|
||
if [ -f "/root/.ssh/id_rsa" ]; then
|
||
echo -e "${YELLOW}SSH ключ уже существует.${NC}"
|
||
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"
|
||
fi
|
||
else
|
||
ssh-keygen -t rsa -b 4096 -N "" -f /root/.ssh/id_rsa -q
|
||
log_message "SSH ключ сгенерирован" "$GREEN"
|
||
fi
|
||
|
||
# Настройка SSH конфигурации для стабильного подключения
|
||
log_message "Настройка конфигурации SSH для стабильного подключения..." "$BLUE"
|
||
|
||
# Создание конфига для root с улучшенными настройками
|
||
cat > /root/.ssh/config << EOF
|
||
# Основная конфигурация SSH
|
||
Host tunnel-vps
|
||
HostName $VPS_HOST
|
||
Port $VPS_PORT
|
||
User $VPS_USER
|
||
IdentityFile ~/.ssh/id_rsa
|
||
StrictHostKeyChecking no
|
||
UserKnownHostsFile /dev/null
|
||
ServerAliveInterval 30
|
||
ServerAliveCountMax 3
|
||
ConnectTimeout 30
|
||
TCPKeepAlive yes
|
||
IdentitiesOnly yes
|
||
ExitOnForwardFailure yes
|
||
# Увеличенные настройки для локальной сети
|
||
IPQoS throughput
|
||
Compression yes
|
||
ControlMaster auto
|
||
ControlPath ~/.ssh/control-%r@%h:%p
|
||
ControlPersist 10m
|
||
# Дополнительные настройки стабильности
|
||
GSSAPIAuthentication no
|
||
AddressFamily inet
|
||
Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,aes128-gcm@openssh.com,aes256-ctr,aes192-ctr,aes128-ctr
|
||
MACs hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com,umac-128-etm@openssh.com
|
||
KexAlgorithms curve25519-sha256,curve25519-sha256@libssh.org,diffie-hellman-group-exchange-sha256
|
||
|
||
Host *
|
||
# Глобальные настройки для всех хостов
|
||
StrictHostKeyChecking no
|
||
UserKnownHostsFile /dev/null
|
||
ServerAliveInterval 30
|
||
ServerAliveCountMax 3
|
||
TCPKeepAlive yes
|
||
Compression yes
|
||
ControlMaster auto
|
||
ControlPath ~/.ssh/control-%r@%h:%p
|
||
ControlPersist 10m
|
||
ConnectTimeout 30
|
||
# Настройки для локальной сети
|
||
GSSAPIAuthentication no
|
||
AddressFamily inet
|
||
# Увеличение размера буферов
|
||
SendEnv LANG LC_*
|
||
HashKnownHosts yes
|
||
# Настройки переподключения
|
||
RekeyLimit 1G 1h
|
||
EOF
|
||
|
||
chmod 600 /root/.ssh/config
|
||
|
||
# Настройка SSH демона для локальных подключений
|
||
log_message "Настройка SSH демона для локальных подключений..." "$BLUE"
|
||
|
||
# Бэкап оригинального конфига
|
||
SSHD_CONFIG="/etc/ssh/sshd_config"
|
||
if [ -f "$SSHD_CONFIG" ]; then
|
||
cp "$SSHD_CONFIG" "${SSHD_CONFIG}.backup.$(date +%Y%m%d%H%M%S)"
|
||
|
||
# Улучшенные настройки для стабильности
|
||
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"
|
||
)
|
||
|
||
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 демон
|
||
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}"
|
||
|
||
# Запрос пароля для копирования ключа
|
||
safe_read "Введите пароль для $VPS_USER@$VPS_HOST (или нажмите Enter для пропуска): " "" VPS_PASSWORD yes
|
||
|
||
if [ -n "$VPS_PASSWORD" ]; then
|
||
echo ""
|
||
echo -e "${CYAN}Попытка копирования ключа с использованием пароля...${NC}"
|
||
|
||
# Установка 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 "Не удалось скопировать ключ через sshpass" "$YELLOW"
|
||
echo -e "${YELLOW}Попробуйте скопировать ключ вручную${NC}"
|
||
fi
|
||
else
|
||
echo -e "${YELLOW}sshpass не установлен, пропускаю автоматическое копирование${NC}"
|
||
fi
|
||
|
||
# Очистка временного файла
|
||
rm -f "$SSH_ASKPASS"
|
||
else
|
||
echo -e "${YELLOW}Пароль не введен, пропускаю автоматическое копирование ключа${NC}"
|
||
fi
|
||
|
||
# Альтернативный метод копирования ключа
|
||
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 ""
|
||
|
||
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=10 \
|
||
-o StrictHostKeyChecking=no \
|
||
"$VPS_USER@$VPS_HOST" \
|
||
"echo 'SSH подключение успешно!'" 2>&1; then
|
||
log_message "Тестовое подключение прошло успешно!" "$GREEN"
|
||
echo -e "${GREEN}✓ SSH ключ настроен корректно${NC}"
|
||
else
|
||
log_message "Тестовое подключение не удалось" "$YELLOW"
|
||
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/" ] && [ "$(ls -A /home/ 2>/dev/null)" ]; then
|
||
echo ""
|
||
safe_read "Настроить SSH для обычных пользователей системы? (y/n): " "n" SETUP_USERS no
|
||
|
||
if [[ "$SETUP_USERS" =~ ^[Yy]$ ]]; then
|
||
log_message "Настройка SSH для всех пользователей системы..." "$CYAN"
|
||
|
||
for HOME_DIR in /home/*; do
|
||
if [ -d "$HOME_DIR" ] && [ "$HOME_DIR" != "/home/*" ]; then
|
||
USER=$(basename "$HOME_DIR")
|
||
USER_SSH_DIR="$HOME_DIR/.ssh"
|
||
|
||
echo -e "${CYAN}Настройка пользователя: $USER${NC}"
|
||
|
||
mkdir -p "$USER_SSH_DIR"
|
||
chmod 700 "$USER_SSH_DIR"
|
||
chown "$USER:$USER" "$USER_SSH_DIR"
|
||
|
||
# Копируем конфиг
|
||
cp /root/.ssh/config "$USER_SSH_DIR/config" 2>/dev/null
|
||
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
|
||
|
||
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"
|
||
chmod 600 "$USER_SSH_DIR/id_rsa" 2>/dev/null
|
||
chmod 644 "$USER_SSH_DIR/id_rsa.pub" 2>/dev/null
|
||
echo -e " ${GREEN}✓ Ключ скопирован для $USER${NC}"
|
||
fi
|
||
fi
|
||
done
|
||
fi
|
||
fi
|
||
|
||
# Сохранение настроек VPS для использования в скриптах
|
||
log_message "Сохранение настроек VPS..." "$BLUE"
|
||
|
||
mkdir -p /etc/ssh_tunnel
|
||
cat > /etc/ssh_tunnel/vps_settings.conf << EOF
|
||
# Настройки VPS для автономных туннелей
|
||
VPS_HOST="$VPS_HOST"
|
||
VPS_PORT="$VPS_PORT"
|
||
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"
|
||
|
||
# Создание директорий
|
||
mkdir -p /opt/ssh_tunnel_manager
|
||
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
|
||
|
||
# Создание основного скрипта менеджера с корректным завершением EOF
|
||
cat > /opt/ssh_tunnel_manager/manager.sh << 'EOFMGR'
|
||
#!/bin/bash
|
||
|
||
# Основной скрипт менеджера SSH туннелей
|
||
# Версия 4.0 - Стабильное меню
|
||
|
||
# Конфигурация
|
||
CONFIG_DIR="/etc/ssh_tunnel"
|
||
LOG_DIR="/var/log/ssh_tunnel"
|
||
SERVICE_DIR="/etc/systemd/system"
|
||
SCRIPT_DIR="/opt/ssh_tunnel_manager"
|
||
|
||
# Цвета
|
||
RED='\033[0;31m'
|
||
GREEN='\033[0;32m'
|
||
YELLOW='\033[1;33m'
|
||
BLUE='\033[0;34m'
|
||
CYAN='\033[0;36m'
|
||
PURPLE='\033[0;35m'
|
||
NC='\033[0m'
|
||
BOLD='\033[1m'
|
||
|
||
# Глобальные переменные
|
||
VPS_HOST=""
|
||
VPS_PORT="22"
|
||
VPS_USER=""
|
||
|
||
# Загрузка настроек VPS если есть
|
||
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}"
|
||
return 1
|
||
fi
|
||
|
||
echo -e "${CYAN}Проверка подключения к ${VPS_USER}@${VPS_HOST}:${VPS_PORT}...${NC}"
|
||
|
||
if timeout 10 ssh -p "$VPS_PORT" \
|
||
-o BatchMode=yes \
|
||
-o ConnectTimeout=5 \
|
||
-o StrictHostKeyChecking=no \
|
||
"${VPS_USER}@${VPS_HOST}" \
|
||
"echo 'Connected' && exit 0" 2>/dev/null; then
|
||
echo -e "${GREEN}✓ Подключение успешно${NC}"
|
||
return 0
|
||
else
|
||
echo -e "${RED}✗ Не удалось подключиться${NC}"
|
||
return 1
|
||
fi
|
||
}
|
||
|
||
# Функция настройки нового VPS
|
||
setup_new_vps() {
|
||
echo -e "${BOLD}${CYAN}Настройка нового VPS подключения${NC}"
|
||
echo -e "${YELLOW}========================================${NC}"
|
||
|
||
read -p "Введите IP адрес или домен VPS: " NEW_VPS_HOST
|
||
read -p "Введите порт SSH (22): " NEW_VPS_PORT
|
||
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 5 ssh -p "$NEW_VPS_PORT" \
|
||
-o ConnectTimeout=3 \
|
||
-o StrictHostKeyChecking=no \
|
||
"$NEW_VPS_USER@$NEW_VPS_HOST" \
|
||
"echo 'OK'" 2>/dev/null; then
|
||
echo -e "${GREEN}✓ Подключение работает${NC}"
|
||
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 << CONFIGVPS
|
||
# Настройки 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')"
|
||
CONFIGVPS
|
||
|
||
echo -e "${GREEN}Настройки сохранены!${NC}"
|
||
VPS_HOST="$NEW_VPS_HOST"
|
||
VPS_PORT="$NEW_VPS_PORT"
|
||
VPS_USER="$NEW_VPS_USER"
|
||
|
||
read -p "Нажмите Enter для продолжения..."
|
||
}
|
||
|
||
# Создание туннеля
|
||
create_tunnel() {
|
||
echo -e "${CYAN}Создание нового туннеля...${NC}"
|
||
|
||
if [ -z "$VPS_HOST" ]; then
|
||
echo -e "${RED}Сначала настройте VPS (опция 9)${NC}"
|
||
sleep 2
|
||
return
|
||
fi
|
||
|
||
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)"
|
||
CONFIG_FILE="/etc/ssh_tunnel/${TUNNEL_ID}.conf"
|
||
|
||
cat > "$CONFIG_FILE" << CONFTUN
|
||
TUNNEL_ID="$TUNNEL_ID"
|
||
VPS_HOST="$VPS_HOST"
|
||
VPS_PORT="$VPS_PORT"
|
||
VPS_USER="$VPS_USER"
|
||
LOCAL_PORT="$LOCAL_PORT"
|
||
REMOTE_PORT="$REMOTE_PORT"
|
||
CREATED="$(date '+%Y-%m-%d %H:%M:%S')"
|
||
CONFTUN
|
||
|
||
echo -e "${GREEN}Туннель создан! Конфиг: $CONFIG_FILE${NC}"
|
||
|
||
# Создание службы
|
||
SERVICE_FILE="/etc/systemd/system/ssh-tunnel-${TUNNEL_ID}.service"
|
||
|
||
cat > "$SERVICE_FILE" << SERVICETUN
|
||
[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
|
||
SERVICETUN
|
||
|
||
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 для продолжения..."
|
||
}
|
||
|
||
# Быстрый SSH туннель
|
||
quick_ssh_tunnel() {
|
||
echo -e "${CYAN}Создание быстрого SSH туннеля...${NC}"
|
||
|
||
if [ -z "$VPS_HOST" ]; then
|
||
echo -e "${RED}Сначала настройте VPS (опция 9)${NC}"
|
||
sleep 2
|
||
return
|
||
fi
|
||
|
||
LOCAL_PORT="22"
|
||
REMOTE_PORT="10022"
|
||
|
||
echo -e "${YELLOW}Будет создан туннель: localhost:22 -> ${VPS_HOST}:${REMOTE_PORT}${NC}"
|
||
|
||
TUNNEL_ID="ssh_tunnel_${REMOTE_PORT}"
|
||
CONFIG_FILE="/etc/ssh_tunnel/${TUNNEL_ID}.conf"
|
||
|
||
cat > "$CONFIG_FILE" << CONFFAST
|
||
TUNNEL_ID="$TUNNEL_ID"
|
||
VPS_HOST="$VPS_HOST"
|
||
VPS_PORT="$VPS_PORT"
|
||
VPS_USER="$VPS_USER"
|
||
LOCAL_PORT="$LOCAL_PORT"
|
||
REMOTE_PORT="$REMOTE_PORT"
|
||
CREATED="$(date '+%Y-%m-%d %H:%M:%S')"
|
||
TYPE="ssh"
|
||
CONFFAST
|
||
|
||
SERVICE_FILE="/etc/systemd/system/ssh-tunnel-${TUNNEL_ID}.service"
|
||
|
||
cat > "$SERVICE_FILE" << SERVICEFAST
|
||
[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
|
||
SERVICEFAST
|
||
|
||
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}"
|
||
|
||
read -p "Нажмите Enter для продолжения..."
|
||
}
|
||
|
||
# Управление туннелями
|
||
manage_tunnels() {
|
||
while true; do
|
||
clear
|
||
echo -e "${BOLD}${CYAN}Управление туннелями${NC}"
|
||
echo -e "${YELLOW}=====================${NC}"
|
||
echo ""
|
||
|
||
# Список туннелей
|
||
count=0
|
||
declare -A tunnels
|
||
|
||
# Исправленный цикл без синтаксической ошибки
|
||
for conf in /etc/ssh_tunnel/*.conf; do
|
||
if [ ! -f "$conf" ]; then
|
||
continue
|
||
fi
|
||
((count++))
|
||
tunnels[$count]="$conf"
|
||
tunnel_name=$(basename "$conf" .conf)
|
||
echo -e "${CYAN}[$count]${NC} $tunnel_name"
|
||
done
|
||
|
||
if [ $count -eq 0 ]; then
|
||
echo -e "${YELLOW}Нет настроенных туннелей${NC}"
|
||
fi
|
||
|
||
echo ""
|
||
echo -e "${CYAN}[s]${NC} Показать статус всех туннелей"
|
||
echo -e "${CYAN}[r]${NC} Перезапустить все туннели"
|
||
echo -e "${CYAN}[b]${NC} Назад в главное меню"
|
||
echo ""
|
||
|
||
clear_input_buffer
|
||
read -p "Выберите опцию: " choice
|
||
|
||
case $choice in
|
||
b|B) return ;;
|
||
s|S)
|
||
echo -e "${CYAN}Статус туннелей:${NC}"
|
||
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
|
||
if [ ! -f "$conf" ]; then
|
||
continue
|
||
fi
|
||
tunnel_name=$(basename "$conf" .conf)
|
||
systemctl restart "ssh-tunnel-${tunnel_name}.service" 2>/dev/null
|
||
echo -e " ${GREEN}✓${NC} $tunnel_name перезапущен"
|
||
done
|
||
read -p "Нажмите Enter для продолжения..."
|
||
;;
|
||
*)
|
||
if [[ $choice =~ ^[0-9]+$ ]] && [ $choice -ge 1 ] && [ $choice -le $count ]; then
|
||
manage_single_tunnel "${tunnels[$choice]}"
|
||
else
|
||
echo -e "${RED}Неверный выбор${NC}"
|
||
sleep 1
|
||
fi
|
||
;;
|
||
esac
|
||
done
|
||
}
|
||
|
||
# Управление одним туннелем
|
||
manage_single_tunnel() {
|
||
local conf="$1"
|
||
local tunnel_name=$(basename "$conf" .conf)
|
||
|
||
source "$conf" 2>/dev/null || {
|
||
echo -e "${RED}Ошибка загрузки конфигурации${NC}"
|
||
return
|
||
}
|
||
|
||
while true; do
|
||
clear
|
||
echo -e "${BOLD}${CYAN}Управление туннелем: $tunnel_name${NC}"
|
||
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:-22}"
|
||
echo ""
|
||
|
||
# Проверка статуса
|
||
if systemctl is-active --quiet "ssh-tunnel-${tunnel_name}.service" 2>/dev/null; then
|
||
echo -e "${GREEN}✓ Служба активна${NC}"
|
||
else
|
||
echo -e "${RED}✗ Служба неактивна${NC}"
|
||
fi
|
||
|
||
echo ""
|
||
echo -e "${CYAN}[1]${NC} Перезапустить туннель"
|
||
echo -e "${CYAN}[2]${NC} Остановить туннель"
|
||
echo -e "${CYAN}[3]${NC} Запустить туннель"
|
||
echo -e "${CYAN}[4]${NC} Показать логи"
|
||
echo -e "${CYAN}[5]${NC} Удалить туннель"
|
||
echo -e "${CYAN}[6]${NC} Назад"
|
||
echo ""
|
||
|
||
clear_input_buffer
|
||
read -p "Выберите действие: " action
|
||
|
||
case $action in
|
||
1)
|
||
systemctl restart "ssh-tunnel-${tunnel_name}.service" 2>/dev/null
|
||
echo -e "${GREEN}Туннель перезапущен${NC}"
|
||
sleep 1
|
||
;;
|
||
2)
|
||
systemctl stop "ssh-tunnel-${tunnel_name}.service" 2>/dev/null
|
||
echo -e "${YELLOW}Туннель остановлен${NC}"
|
||
sleep 1
|
||
;;
|
||
3)
|
||
systemctl start "ssh-tunnel-${tunnel_name}.service" 2>/dev/null
|
||
echo -e "${GREEN}Туннель запущен${NC}"
|
||
sleep 1
|
||
;;
|
||
4)
|
||
echo -e "${CYAN}Логи туннеля:${NC}"
|
||
tail -20 "/var/log/ssh_tunnel/${tunnel_name}.log" 2>/dev/null || echo "Логи отсутствуют"
|
||
read -p "Нажмите Enter для продолжения..."
|
||
;;
|
||
5)
|
||
read -p "Вы уверены, что хотите удалить туннель $tunnel_name? (y/n): " confirm
|
||
if [[ "$confirm" =~ ^[Yy]$ ]]; then
|
||
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" 2>/dev/null
|
||
systemctl daemon-reload
|
||
echo -e "${GREEN}Туннель удален${NC}"
|
||
return
|
||
fi
|
||
;;
|
||
6)
|
||
return
|
||
;;
|
||
*)
|
||
echo -e "${RED}Неверный выбор${NC}"
|
||
sleep 1
|
||
;;
|
||
esac
|
||
done
|
||
}
|
||
|
||
# Настройка автозапуска
|
||
setup_autostart() {
|
||
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; do
|
||
if [ ! -f "$conf" ]; then
|
||
continue
|
||
fi
|
||
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}"
|
||
done
|
||
read -p "Нажмите Enter для продолжения..."
|
||
;;
|
||
2)
|
||
for conf in /etc/ssh_tunnel/*.conf; do
|
||
if [ ! -f "$conf" ]; then
|
||
continue
|
||
fi
|
||
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}"
|
||
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
|
||
}
|
||
|
||
# Просмотр логов
|
||
view_logs() {
|
||
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 -e "${CYAN}[5]${NC} Реальный мониторинг"
|
||
echo -e "${CYAN}[6]${NC} Назад"
|
||
echo ""
|
||
|
||
clear_input_buffer
|
||
read -p "Выберите действие: " choice
|
||
|
||
case $choice in
|
||
1)
|
||
echo -e "${CYAN}Доступные логи:${NC}"
|
||
for log in $LOG_DIR/*.log; do
|
||
if [ ! -f "$log" ]; then
|
||
continue
|
||
fi
|
||
echo " $(basename $log)"
|
||
done
|
||
echo ""
|
||
read -p "Введите имя лог-файла: " log_file
|
||
if [ -f "$LOG_DIR/$log_file" ]; then
|
||
less "$LOG_DIR/$log_file"
|
||
else
|
||
echo -e "${RED}Файл не найден${NC}"
|
||
sleep 1
|
||
fi
|
||
;;
|
||
2)
|
||
echo -e "${CYAN}Все логи туннелей:${NC}"
|
||
for log in $LOG_DIR/*.log; do
|
||
if [ ! -f "$log" ]; then
|
||
continue
|
||
fi
|
||
echo -e "\n${YELLOW}=== $(basename $log) ===${NC}"
|
||
tail -5 "$log"
|
||
done
|
||
read -p "Нажмите Enter для продолжения..."
|
||
;;
|
||
3)
|
||
echo -e "${CYAN}Системные логи туннелей:${NC}"
|
||
journalctl -u ssh-tunnel-* --since "1 hour ago" -n 10 2>/dev/null || echo "Логи отсутствуют"
|
||
read -p "Нажмите Enter для продолжения..."
|
||
;;
|
||
4)
|
||
if [ -f "$LOG_DIR/monitor.log" ]; then
|
||
echo -e "${CYAN}Лог монитора:${NC}"
|
||
tail -20 "$LOG_DIR/monitor.log"
|
||
else
|
||
echo -e "${YELLOW}Лог монитора отсутствует${NC}"
|
||
fi
|
||
read -p "Нажмите Enter для продолжения..."
|
||
;;
|
||
5)
|
||
echo -e "${CYAN}Реальный мониторинг логов (Ctrl+C для выхода)${NC}"
|
||
trap 'echo -e "\n${YELLOW}Мониторинг остановлен${NC}"' INT
|
||
tail -f $LOG_DIR/*.log 2>/dev/null
|
||
;;
|
||
6)
|
||
return
|
||
;;
|
||
*)
|
||
echo -e "${RED}Неверный выбор${NC}"
|
||
sleep 1
|
||
;;
|
||
esac
|
||
done
|
||
}
|
||
|
||
# Тестирование подключений
|
||
test_connections() {
|
||
echo -e "${CYAN}Тестирование подключений...${NC}"
|
||
|
||
echo "1) Тест подключения к VPS"
|
||
echo "2) Тест портов туннелей"
|
||
echo "3) Назад"
|
||
|
||
clear_input_buffer
|
||
read -p "Выберите тест: " test_choice
|
||
|
||
case $test_choice in
|
||
1)
|
||
check_ssh_connection
|
||
;;
|
||
2)
|
||
echo -e "${CYAN}Тест портов туннелей:${NC}"
|
||
for conf in /etc/ssh_tunnel/*.conf; do
|
||
if [ ! -f "$conf" ]; then
|
||
continue
|
||
fi
|
||
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
|
||
echo -e "${GREEN}✓ Открыт${NC}"
|
||
else
|
||
echo -e "${RED}✗ Закрыт${NC}"
|
||
fi
|
||
done
|
||
;;
|
||
3)
|
||
return
|
||
;;
|
||
*)
|
||
echo -e "${RED}Неверный выбор${NC}"
|
||
;;
|
||
esac
|
||
|
||
read -p "Нажмите Enter для продолжения..."
|
||
}
|
||
|
||
# Настройка маршрутизации
|
||
setup_routing() {
|
||
echo -e "${CYAN}Настройка маршрутизации...${NC}"
|
||
|
||
echo "1) Показать текущие правила iptables"
|
||
echo "2) Добавить правило перенаправления порта"
|
||
echo "3) Сохранить правила"
|
||
echo "4) Назад"
|
||
|
||
clear_input_buffer
|
||
read -p "Выберите действие: " routing_choice
|
||
|
||
case $routing_choice in
|
||
1)
|
||
echo -e "${CYAN}Текущие правила iptables:${NC}"
|
||
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
|
||
|
||
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)
|
||
if command -v iptables-save &> /dev/null; then
|
||
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
|
||
;;
|
||
4)
|
||
return
|
||
;;
|
||
*)
|
||
echo -e "${RED}Неверный выбор${NC}"
|
||
;;
|
||
esac
|
||
|
||
read -p "Нажмите Enter для продолжения..."
|
||
}
|
||
|
||
# Настройки SSH
|
||
setup_ssh_config() {
|
||
echo -e "${CYAN}Настройка SSH...${NC}"
|
||
|
||
echo "1) Показать текущую конфигурацию SSH"
|
||
echo "2) Перезапустить SSH демон"
|
||
echo "3) Проверить конфигурацию"
|
||
echo "4) Назад"
|
||
|
||
clear_input_buffer
|
||
read -p "Выберите действие: " ssh_choice
|
||
|
||
case $ssh_choice in
|
||
1)
|
||
echo -e "${CYAN}Текущая конфигурация SSH:${NC}"
|
||
grep -E "^(ClientAlive|TCPKeepAlive|ServerAlive|Port|PasswordAuthentication|PermitRootLogin)" /etc/ssh/sshd_config 2>/dev/null || echo "Конфигурация не найдена"
|
||
;;
|
||
2)
|
||
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
|
||
echo -e "${GREEN}✓ Конфигурация SSH корректна${NC}"
|
||
else
|
||
echo -e "${RED}✗ Ошибка в конфигурации SSH${NC}"
|
||
fi
|
||
;;
|
||
4)
|
||
return
|
||
;;
|
||
*)
|
||
echo -e "${RED}Неверный выбор${NC}"
|
||
;;
|
||
esac
|
||
|
||
read -p "Нажмите Enter для продолжения..."
|
||
}
|
||
|
||
# Основное меню
|
||
show_menu() {
|
||
# Загрузка настроек
|
||
load_vps_settings
|
||
|
||
while true; do
|
||
clear
|
||
echo -e "${BOLD}${CYAN}════════════════════════════════════════════════════════════════${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}${NC}"
|
||
else
|
||
echo -e "${RED}VPS не настроен! Выберите опцию 9 для настройки.${NC}"
|
||
fi
|
||
|
||
echo ""
|
||
|
||
# Проверка статуса подключения
|
||
if [ -n "$VPS_HOST" ]; then
|
||
echo -e "${CYAN}Статус подключения:${NC}"
|
||
if check_ssh_connection; then
|
||
echo -e "${GREEN}✓ Соединение с VPS активно${NC}"
|
||
else
|
||
echo -e "${RED}✗ Нет соединения с VPS${NC}"
|
||
fi
|
||
echo ""
|
||
fi
|
||
|
||
echo -e "${BOLD}${YELLOW}[1]${NC} Создать новый автономный туннель"
|
||
echo -e "${BOLD}${YELLOW}[2]${NC} Быстрый туннель (SSH 22 порт)"
|
||
echo -e "${BOLD}${YELLOW}[3]${NC} Управление существующими туннелями"
|
||
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}[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
|
||
1) create_tunnel ;;
|
||
2) quick_ssh_tunnel ;;
|
||
3) manage_tunnels ;;
|
||
4) setup_autostart ;;
|
||
5) view_logs ;;
|
||
6) test_connections ;;
|
||
7) setup_routing ;;
|
||
8) setup_ssh_config ;;
|
||
9) setup_new_vps ;;
|
||
0)
|
||
echo -e "${GREEN}Выход...${NC}"
|
||
exit 0
|
||
;;
|
||
*)
|
||
echo -e "${RED}Неверный выбор. Попробуйте еще раз.${NC}"
|
||
sleep 1
|
||
;;
|
||
esac
|
||
done
|
||
}
|
||
|
||
# Главный цикл
|
||
if [ "$0" = "$BASH_SOURCE" ] || [ "$0" = "./manager.sh" ]; then
|
||
show_menu
|
||
fi
|
||
EOFMGR
|
||
|
||
# Создание файла с цветами
|
||
cat > /opt/ssh_tunnel_manager/colors.sh << 'EOFCOLORS'
|
||
#!/bin/bash
|
||
# Файл цветов для менеджера туннелей
|
||
RED='\033[0;31m'
|
||
GREEN='\033[0;32m'
|
||
YELLOW='\033[1;33m'
|
||
BLUE='\033[0;34m'
|
||
CYAN='\033[0;36m'
|
||
PURPLE='\033[0;35m'
|
||
NC='\033[0m'
|
||
BOLD='\033[1m'
|
||
EOFCOLORS
|
||
|
||
# Делаем скрипт исполняемым
|
||
chmod +x /opt/ssh_tunnel_manager/manager.sh
|
||
chmod +x /opt/ssh_tunnel_manager/colors.sh
|
||
|
||
# Создание символической ссылки
|
||
ln -sf /opt/ssh_tunnel_manager/manager.sh /usr/local/bin/tunnel-manager 2>/dev/null
|
||
|
||
log_message "Основной скрипт установлен в /opt/ssh_tunnel_manager/" "$GREEN"
|
||
}
|
||
|
||
# Настройка systemd служб
|
||
setup_systemd_services() {
|
||
log_message "Настройка systemd служб для автономной работы..." "$CYAN"
|
||
|
||
# Основная служба мониторинга
|
||
cat > /etc/systemd/system/tunnel-monitor.service << EOFSERVICE
|
||
[Unit]
|
||
Description=Мониторинг и восстановление SSH туннелей
|
||
After=network-online.target
|
||
Wants=network-online.target
|
||
|
||
[Service]
|
||
Type=simple
|
||
ExecStart=/opt/ssh_tunnel_manager/monitor.sh
|
||
Restart=always
|
||
RestartSec=30
|
||
User=root
|
||
|
||
StandardOutput=append:/var/log/ssh_tunnel/monitor.log
|
||
StandardError=append:/var/log/ssh_tunnel/monitor.log
|
||
|
||
[Install]
|
||
WantedBy=multi-user.target
|
||
EOFSERVICE
|
||
|
||
# Скрипт мониторинга
|
||
cat > /opt/ssh_tunnel_manager/monitor.sh << 'EOFMONITOR'
|
||
#!/bin/bash
|
||
# Скрипт мониторинга туннелей
|
||
|
||
LOG_FILE="/var/log/ssh_tunnel/monitor.log"
|
||
CONFIG_DIR="/etc/ssh_tunnel"
|
||
|
||
log() {
|
||
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" >> "$LOG_FILE"
|
||
}
|
||
|
||
check_tunnel() {
|
||
local config_file="$1"
|
||
local tunnel_name=$(basename "$config_file" .conf)
|
||
|
||
if [ ! -f "$config_file" ]; then
|
||
return 1
|
||
fi
|
||
|
||
source "$config_file"
|
||
|
||
# Проверяем, работает ли туннель
|
||
if ps aux | grep -v grep | grep -q "autossh.*$REMOTE_PORT.*$VPS_HOST"; then
|
||
# Проверяем доступность порта
|
||
if timeout 2 nc -z localhost "$LOCAL_PORT" 2>/dev/null; then
|
||
log "Туннель $tunnel_name: OK"
|
||
return 0
|
||
fi
|
||
fi
|
||
|
||
log "Туннель $tunnel_name: FAILED - перезапуск"
|
||
|
||
# Перезапускаем службу
|
||
if systemctl is-active --quiet "ssh-tunnel-$tunnel_name.service" 2>/dev/null; then
|
||
systemctl restart "ssh-tunnel-$tunnel_name.service"
|
||
else
|
||
# Запускаем туннель напрямую
|
||
/usr/bin/autossh -M 0 -N \
|
||
-o "ExitOnForwardFailure=yes" \
|
||
-o "ServerAliveInterval=30" \
|
||
-o "ServerAliveCountMax=3" \
|
||
-R "${REMOTE_PORT}:localhost:${LOCAL_PORT}" \
|
||
"${VPS_USER}@${VPS_HOST}" -p "${VPS_PORT}" &
|
||
fi
|
||
|
||
return 1
|
||
}
|
||
|
||
log "Запуск монитора SSH туннелей"
|
||
|
||
while true; do
|
||
# Проверяем все конфигурации
|
||
for config in "$CONFIG_DIR"/*.conf; do
|
||
if [ -f "$config" ]; then
|
||
check_tunnel "$config"
|
||
fi
|
||
done
|
||
|
||
sleep 60
|
||
done
|
||
EOFMONITOR
|
||
|
||
chmod +x /opt/ssh_tunnel_manager/monitor.sh
|
||
|
||
# Создание таймера для периодической проверки
|
||
cat > /etc/systemd/system/tunnel-check.timer << EOFTIMER
|
||
[Unit]
|
||
Description=Периодическая проверка SSH туннелей
|
||
|
||
[Timer]
|
||
OnBootSec=5min
|
||
OnUnitActiveSec=5min
|
||
AccuracySec=1min
|
||
|
||
[Install]
|
||
WantedBy=timers.target
|
||
EOFTIMER
|
||
|
||
# Включение служб
|
||
systemctl daemon-reload 2>/dev/null
|
||
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"
|
||
}
|
||
|
||
# Создание примера туннеля
|
||
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
|
||
|
||
if [[ "$CREATE_EXAMPLE" =~ ^[Yy]$ ]]; then
|
||
cat > /etc/ssh_tunnel/example_ssh.conf << EOFEXAMPLE
|
||
# Пример туннеля для SSH доступа
|
||
TUNNEL_NAME="example_ssh"
|
||
VPS_HOST="$VPS_HOST"
|
||
VPS_PORT="$VPS_PORT"
|
||
VPS_USER="$VPS_USER"
|
||
LOCAL_PORT="22"
|
||
REMOTE_PORT="10022"
|
||
ENABLED="true"
|
||
EOFEXAMPLE
|
||
|
||
# Создание службы для примера
|
||
cat > /etc/systemd/system/ssh-tunnel-example_ssh.service << EOFEXSERVICE
|
||
[Unit]
|
||
Description=Пример SSH туннеля (22->10022)
|
||
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} \\
|
||
\${VPS_USER}@\${VPS_HOST} -p \${VPS_PORT}
|
||
Restart=always
|
||
RestartSec=10
|
||
User=root
|
||
|
||
StandardOutput=append:/var/log/ssh_tunnel/example_ssh.log
|
||
StandardError=append:/var/log/ssh_tunnel/example_ssh.log
|
||
|
||
[Install]
|
||
WantedBy=multi-user.target
|
||
EOFEXSERVICE
|
||
|
||
systemctl daemon-reload 2>/dev/null
|
||
systemctl enable ssh-tunnel-example_ssh.service 2>/dev/null
|
||
systemctl start ssh-tunnel-example_ssh.service 2>/dev/null
|
||
|
||
log_message "Пример туннеля создан!" "$GREEN"
|
||
echo -e "${CYAN}Для подключения используйте:${NC}"
|
||
echo -e "${BOLD}ssh -p 10022 $VPS_USER@$VPS_HOST${NC}"
|
||
echo ""
|
||
echo -e "${YELLOW}Проверьте подключение:${NC}"
|
||
echo -e " systemctl status ssh-tunnel-example_ssh.service"
|
||
echo -e " tail -f /var/log/ssh_tunnel/example_ssh.log"
|
||
fi
|
||
fi
|
||
}
|
||
|
||
# Завершение установки
|
||
finish_installation() {
|
||
echo ""
|
||
echo -e "${BOLD}${GREEN}════════════════════════════════════════════════════════════════${NC}"
|
||
echo -e "${BOLD}${GREEN} УСТАНОВКА УСПЕШНО ЗАВЕРШЕНА! ${NC}"
|
||
echo -e "${BOLD}${GREEN}════════════════════════════════════════════════════════════════${NC}"
|
||
echo ""
|
||
|
||
log_message "Итоги установки:" "$CYAN"
|
||
echo -e "${GREEN}✓${NC} Зависимости установлены"
|
||
echo -e "${GREEN}✓${NC} SSH ключи сгенерированы и настроены"
|
||
echo -e "${GREEN}✓${NC} SSH конфигурация улучшена для стабильности"
|
||
echo -e "${GREEN}✓${NC} Основной скрипт установлен"
|
||
echo -e "${GREEN}✓${NC} Systemd службы настроены"
|
||
echo -e "${GREEN}✓${NC} Автозапуск включен"
|
||
echo ""
|
||
|
||
if [ -n "$VPS_HOST" ]; then
|
||
echo -e "${BOLD}Информация о подключении:${NC}"
|
||
echo -e " VPS: $VPS_USER@$VPS_HOST:$VPS_PORT"
|
||
echo -e " SSH ключ: /root/.ssh/id_rsa"
|
||
echo -e " Конфиг SSH: /root/.ssh/config"
|
||
echo ""
|
||
fi
|
||
|
||
echo -e "${BOLD}Команды для управления:${NC}"
|
||
echo -e " ${CYAN}tunnel-manager${NC} - запуск менеджера туннелей"
|
||
echo -e " ${CYAN}systemctl status tunnel-monitor${NC} - статус монитора"
|
||
echo -e " ${CYAN}journalctl -u tunnel-monitor -f${NC} - просмотр логов"
|
||
echo ""
|
||
|
||
echo -e "${BOLD}Автономная работа гарантирована!${NC}"
|
||
echo -e "Система автоматически запустится после перезагрузки."
|
||
echo ""
|
||
echo -e "${YELLOW}Полный лог установки: $LOG_FILE${NC}"
|
||
echo ""
|
||
|
||
# Запрос на перезагрузку
|
||
safe_read "Перезагрузить систему для применения всех настроек? (y/n): " "n" REBOOT_NOW no
|
||
|
||
if [[ "$REBOOT_NOW" =~ ^[Yy]$ ]]; then
|
||
log_message "Перезагрузка системы по запросу пользователя..." "$YELLOW"
|
||
echo -e "${YELLOW}Система перезагрузится через 5 секунд...${NC}"
|
||
sleep 5
|
||
reboot
|
||
else
|
||
echo ""
|
||
echo -e "${GREEN}Для запуска менеджера выполните:${NC}"
|
||
echo -e "${BOLD}tunnel-manager${NC}"
|
||
echo ""
|
||
fi
|
||
}
|
||
|
||
# Главная функция установки
|
||
main_installation() {
|
||
log_message "Начало установки автономного менеджера SSH туннелей" "$CYAN"
|
||
|
||
# Определяем дистрибутив
|
||
detect_distro
|
||
|
||
# Устанавливаем зависимости
|
||
install_dependencies
|
||
|
||
# Настраиваем SSH (теперь будет запрашивать данные)
|
||
setup_ssh
|
||
|
||
# Устанавливаем основной скрипт
|
||
install_main_script
|
||
|
||
# Настраиваем systemd службы
|
||
setup_systemd_services
|
||
|
||
# Создаем пример туннеля
|
||
create_example_tunnel
|
||
|
||
# Завершаем установку
|
||
finish_installation
|
||
}
|
||
|
||
# Запуск установки
|
||
main_installation |