Files
vps_ssh_tunel/install_ssh_tunnel.sh
2025-12-22 18:24:52 +00:00

1672 lines
64 KiB
Bash
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/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_input() {
local prompt="$1"
local default="$2"
local var_name="$3"
local is_password="$4"
local max_attempts="${5:-3}"
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
else
read -p "$prompt" input
fi
input="${input:-$default}"
if [ -n "$input" ]; then
eval "$var_name=\"$input\""
return 0
elif [[ $attempt -lt $max_attempts ]]; then
echo -e "${YELLOW}Поле не может быть пустым! Попытка $attempt из $max_attempts${NC}"
fi
done
echo -e "${RED}Превышено максимальное количество попыток ввода. Выход.${NC}"
exit 1
}
# Функция проверки ошибок
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
}
# Определение дистрибутива
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"
return 0
}
# Установка зависимостей
install_dependencies() {
log_message "Установка необходимых зависимостей..." "$CYAN"
case $OS in
ubuntu|debian)
log_message "Обновление списка пакетов..." "$BLUE"
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"
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"
if ! command -v autossh &> /dev/null; then
log_message "Установка autossh вручную..." "$BLUE"
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
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 с проверкой
local vps_data_ok=false
local max_attempts=3
local VPS_HOST=""
local VPS_PORT=""
local VPS_USER=""
for ((attempt=1; attempt<=max_attempts; attempt++)); do
echo -e "${CYAN}Введите данные для подключения к VPS (попытка $attempt из $max_attempts):${NC}"
echo ""
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) Другой пользователь"
read -p "Ваш выбор [1-2]: " USER_CHOICE
if [ "$USER_CHOICE" = "1" ] || [ -z "$USER_CHOICE" ]; then
VPS_USER="root"
echo -e "${YELLOW}Будет использоваться пользователь: root${NC}"
else
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 ""
echo -e "${CYAN}Проверка введенных данных:${NC}"
echo -e " VPS: ${YELLOW}$VPS_USER@$VPS_HOST:$VPS_PORT${NC}"
echo ""
read -p "Все верно? (y/n): " CONFIRM
if [[ "$CONFIRM" =~ ^[Yy]$ ]] || [ -z "$CONFIRM" ]; then
vps_data_ok=true
break
else
echo -e "${YELLOW}Повторите ввод данных...${NC}"
echo ""
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}"
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) Не блокирует ли брандмауэр подключение"
read -p "Продолжить все равно? (y/n): " CONTINUE
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}"
read -p "Сгенерировать новый? (y/n): " GEN_NEW
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 << 'EOFCONFIG'
# Основная конфигурация 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
EOFCONFIG
# Замена переменных в конфиге
sed -i "s/\$VPS_HOST/$VPS_HOST/g" /root/.ssh/config
sed -i "s/\$VPS_PORT/$VPS_PORT/g" /root/.ssh/config
sed -i "s/\$VPS_USER/$VPS_USER/g" /root/.ssh/config
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}"
# Запрос пароля для копирования ключа
read -s -p "Введите пароль для $VPS_USER@$VPS_HOST (или нажмите Enter для пропуска): " VPS_PASSWORD
echo
if [ -n "$VPS_PASSWORD" ]; then
echo ""
echo -e "${CYAN}Попытка копирования ключа с использованием пароля...${NC}"
# Пытаемся скопировать ключ с использованием 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
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 ""
read -p "Нажмите Enter после добавления ключа на VPS..." WAIT
# Тестовое подключение
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 | tee -a "$LOG_FILE"; then
log_message "Тестовое подключение прошло успешно!" "$GREEN"
echo -e "${GREEN}✓ SSH ключ настроен корректно${NC}"
else
log_message "Тестовое подключение не удалось" "$YELLOW"
echo -e "${YELLOW}Не удалось подключиться без пароля${NC}"
echo -e "${YELLOW}Убедитесь, что ключ добавлен в authorized_keys на VPS${NC}"
read -p "Продолжить установку? (y/n): " CONTINUE_INSTALL
if [[ ! "$CONTINUE_INSTALL" =~ ^[Yy]$ ]]; then
exit 1
fi
fi
# Настройка для не-root пользователей
if [[ $EUID -eq 0 ]] && [ -d "/home/" ] && [ "$(ls -A /home/ 2>/dev/null)" ]; then
echo ""
read -p "Настроить SSH для обычных пользователей системы? (y/n): " SETUP_USERS
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
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
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 << EOFSETTINGS
# Настройки VPS для автономных туннелей
VPS_HOST="$VPS_HOST"
VPS_PORT="$VPS_PORT"
VPS_USER="$VPS_USER"
CONFIGURED_ON="$(date '+%Y-%m-%d %H:%M:%S')"
EOFSETTINGS
chmod 600 /etc/ssh_tunnel/vps_settings.conf
log_message "Настройки SSH сохранены в /etc/ssh_tunnel/vps_settings.conf" "$GREEN"
# Экспорт переменных для других функций
export VPS_HOST
export VPS_PORT
export VPS_USER
return 0
}
# Установка основного скрипта управления
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
# Создание основного скрипта менеджера
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_input() {
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 для продолжения..."
return 0
}
# Создание туннеля
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 для продолжения..."
return 0
}
# Быстрый 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 для продолжения..."
return 0
}
# Управление туннелями
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
# Пропускаем файл настроек VPS
if [[ "$(basename "$conf")" == "vps_settings.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" ] || [[ "$(basename "$conf")" == "vps_settings.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)
if [ ! -f "$conf" ]; then
echo -e "${RED}Конфигурация не найдена${NC}"
return 1
fi
# Загружаем настройки туннеля
LOCAL_PORT=""
REMOTE_PORT=""
VPS_HOST=""
VPS_PORT=""
VPS_USER=""
source "$conf" 2>/dev/null || {
echo -e "${RED}Ошибка загрузки конфигурации${NC}"
return 1
}
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}"
if [ -f "/var/log/ssh_tunnel/${tunnel_name}.log" ]; then
tail -20 "/var/log/ssh_tunnel/${tunnel_name}.log"
else
echo "Логи отсутствуют"
fi
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}"
sleep 1
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" ] || [[ "$(basename "$conf")" == "vps_settings.conf" ]]; then
continue
fi
tunnel_name=$(basename "$conf" .conf)
if systemctl enable "ssh-tunnel-${tunnel_name}.service" 2>/dev/null; then
echo -e "${GREEN}✓ Автозапуск включен для $tunnel_name${NC}"
else
echo -e "${RED}✗ Ошибка для $tunnel_name${NC}"
fi
done
read -p "Нажмите Enter для продолжения..."
;;
2)
for conf in /etc/ssh_tunnel/*.conf; do
if [ ! -f "$conf" ] || [[ "$(basename "$conf")" == "vps_settings.conf" ]]; then
continue
fi
tunnel_name=$(basename "$conf" .conf)
if systemctl disable "ssh-tunnel-${tunnel_name}.service" 2>/dev/null; then
echo -e "${YELLOW}✓ Автозапуск выключен для $tunnel_name${NC}"
else
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
}
# Просмотр логов
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_file in "$LOG_DIR"/*.log; do
if [ -f "$log_file" ]; then
echo " $(basename "$log_file")"
fi
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_file in "$LOG_DIR"/*.log; do
if [ ! -f "$log_file" ]; then
continue
fi
echo -e "\n${YELLOW}=== $(basename "$log_file") ===${NC}"
tail -5 "$log_file"
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}"; return' INT
tail -f "$LOG_DIR"/*.log 2>/dev/null || echo "Нет логов для мониторинга"
;;
6)
return
;;
*)
echo -e "${RED}Неверный выбор${NC}"
sleep 1
;;
esac
done
}
# Тестирование подключений
test_connections() {
while true; do
clear
echo -e "${CYAN}Тестирование подключений...${NC}"
echo ""
echo "1) Тест подключения к VPS"
echo "2) Тест портов туннелей"
echo "3) Назад"
echo ""
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" ] || [[ "$(basename "$conf")" == "vps_settings.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 для продолжения..."
done
}
# Настройка маршрутизации
setup_routing() {
while true; do
clear
echo -e "${CYAN}Настройка маршрутизации...${NC}"
echo ""
echo "1) Показать текущие правила iptables"
echo "2) Добавить правило перенаправления порта"
echo "3) Сохранить правила"
echo "4) Назад"
echo ""
clear_input_buffer
read -p "Выберите действие: " routing_choice
case $routing_choice in
1)
echo -e "${CYAN}Текущие правила iptables:${NC}"
if command -v iptables &> /dev/null; then
iptables -t nat -L -n -v 2>/dev/null || echo "Ошибка при получении правил"
else
echo "iptables не установлен"
fi
;;
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
if command -v iptables &> /dev/null; 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}iptables не установлен${NC}"
fi
else
echo -e "${RED}Не все поля заполнены${NC}"
fi
;;
3)
if command -v iptables-save &> /dev/null; then
mkdir -p /etc/iptables
if iptables-save > /etc/iptables/rules.v4 2>/dev/null; then
echo -e "${GREEN}Правила сохранены${NC}"
else
echo -e "${RED}Ошибка сохранения${NC}"
fi
else
echo -e "${RED}iptables-save не найден${NC}"
fi
;;
4)
return
;;
*)
echo -e "${RED}Неверный выбор${NC}"
;;
esac
read -p "Нажмите Enter для продолжения..."
done
}
# Настройки SSH
setup_ssh_config() {
while true; do
clear
echo -e "${CYAN}Настройка SSH...${NC}"
echo ""
echo "1) Показать текущую конфигурацию SSH"
echo "2) Перезапустить SSH демон"
echo "3) Проверить конфигурацию"
echo "4) Назад"
echo ""
clear_input_buffer
read -p "Выберите действие: " ssh_choice
case $ssh_choice in
1)
echo -e "${CYAN}Текущая конфигурация SSH:${NC}"
if [ -f /etc/ssh/sshd_config ]; then
grep -E "^(ClientAlive|TCPKeepAlive|ServerAlive|Port|PasswordAuthentication|PermitRootLogin)" /etc/ssh/sshd_config 2>/dev/null || echo "Настройки не найдены"
else
echo "Файл конфигурации не найден"
fi
;;
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 command -v sshd &> /dev/null; then
if sshd -t 2>/dev/null; then
echo -e "${GREEN}✓ Конфигурация SSH корректна${NC}"
else
echo -e "${RED}✗ Ошибка в конфигурации SSH${NC}"
fi
else
echo -e "${RED}sshd не найден${NC}"
fi
;;
4)
return
;;
*)
echo -e "${RED}Неверный выбор${NC}"
;;
esac
read -p "Нажмите Enter для продолжения..."
done
}
# Основное меню
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 > /dev/null 2>&1; 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 [[ "${BASH_SOURCE[0]}" == "${0}" ]]; 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"
return 0
}
# Настройка 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
# Проверяем все конфигурации (кроме vps_settings.conf)
for config in "$CONFIG_DIR"/*.conf; do
if [ -f "$config" ] && [[ "$(basename "$config")" != "vps_settings.conf" ]]; 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"
return 0
}
# Создание примера туннеля
create_example_tunnel() {
log_message "Создание примера SSH туннеля..." "$CYAN"
# Загружаем настройки VPS
if [ -f /etc/ssh_tunnel/vps_settings.conf ]; then
source /etc/ssh_tunnel/vps_settings.conf
fi
if [ -n "$VPS_HOST" ] && [ -n "$VPS_USER" ]; then
read -p "Создать пример туннеля для SSH (порт 22 -> 10022)? (y/n): " CREATE_EXAMPLE
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
else
echo -e "${YELLOW}Не удалось создать пример туннеля: настройки VPS не найдены${NC}"
fi
return 0
}
# Завершение установки
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 ""
# Загружаем настройки VPS для отображения
if [ -f /etc/ssh_tunnel/vps_settings.conf ]; then
source /etc/ssh_tunnel/vps_settings.conf
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 ""
# Запрос на перезагрузку
read -p "Перезагрузить систему для применения всех настроек? (y/n): " REBOOT_NOW
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
return 0
}
# Главная функция установки
main_installation() {
log_message "Начало установки автономного менеджера SSH туннелей" "$CYAN"
# Определяем дистрибутив
detect_distro || {
echo -e "${RED}Не удалось определить дистрибутив${NC}"
exit 1
}
# Устанавливаем зависимости
install_dependencies || {
echo -e "${RED}Не удалось установить зависимости${NC}"
exit 1
}
# Настраиваем SSH
setup_ssh || {
echo -e "${RED}Не удалось настроить SSH${NC}"
exit 1
}
# Устанавливаем основной скрипт
install_main_script || {
echo -e "${RED}Не удалось установить основной скрипт${NC}"
exit 1
}
# Настраиваем systemd службы
setup_systemd_services || {
echo -e "${YELLOW}Не удалось настроить systemd службы${NC}"
}
# Создаем пример туннеля
create_example_tunnel || {
echo -e "${YELLOW}Не удалось создать пример туннеля${NC}"
}
# Завершаем установку
finish_installation
}
# Обработка ошибок и трассировка
set -eE
trap 'echo -e "${RED}Произошла ошибка в строке $LINENO. Проверьте лог: $LOG_FILE${NC}"' ERR
# Запуск установки
main_installation
exit 0