326 lines
10 KiB
Bash
326 lines
10 KiB
Bash
#!/usr/bin/env bash
|
||
|
||
# Установщик автономного менеджера SSH туннелей
|
||
# Версия: 1.0.0
|
||
# Дата: 2025-12-22
|
||
# Авторы: OpenDoor Team
|
||
# Лицензия: MIT
|
||
|
||
set -euo pipefail
|
||
|
||
# Цвета для вывода
|
||
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_$(date '+%Y%m%d_%H%M%S').log"
|
||
|
||
log_message() {
|
||
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" | tee -a "$LOG_FILE"
|
||
}
|
||
|
||
# Проверка прав root
|
||
if [[ $EUID -ne 0 ]]; then
|
||
echo -e "${RED}Этот скрипт требует прав root.${NC}"
|
||
exit 1
|
||
fi
|
||
|
||
clear
|
||
echo -e "${BOLD}${CYAN}════════════════════════════════════════════════════════════════${NC}"
|
||
echo -e "${BOLD}${CYAN} УСТАНОВКА АВТОНОМНОГО МЕНЕДЖЕРА SSH ТУННЕЛЕЙ ${NC}"
|
||
echo -e "${BOLD}${CYAN}════════════════════════════════════════════════════════════════${NC}"
|
||
echo ""
|
||
|
||
# Определение дистрибутива
|
||
OS=""
|
||
VERSION=""
|
||
if [ -f /etc/os-release ]; then
|
||
. /etc/os-release
|
||
OS=$ID
|
||
VERSION=$VERSION_ID
|
||
elif [ -f /etc/redhat-release ]; then
|
||
OS="rhel"
|
||
VERSION=$(sed 's/.*release \([0-9]\).*/\1/' /etc/redhat-release)
|
||
else
|
||
echo -e "${RED}Неизвестная ОС.${NC}"
|
||
exit 1
|
||
fi
|
||
|
||
# Установка зависимостей
|
||
install_dependencies() {
|
||
log_message "Установка зависимостей..."
|
||
case $OS in
|
||
ubuntu|debian)
|
||
apt-get update
|
||
apt-get install -y autossh openssh-client sshpass curl git net-tools
|
||
;;
|
||
centos|rhel|fedora|rocky|almalinux)
|
||
if command -v dnf &> /dev/null; then
|
||
dnf install -y autossh openssh-clients net-tools curl git sshpass
|
||
else
|
||
yum install -y autossh openssh-clients net-tools curl git sshpass
|
||
fi
|
||
;;
|
||
*)
|
||
echo -e "${RED}Не поддерживаемый дистрибутив.${NC}"
|
||
exit 1
|
||
;;
|
||
esac
|
||
log_message "Зависимости установлены."
|
||
}
|
||
|
||
# Настройка SSH
|
||
setup_ssh() {
|
||
log_message "Настройка SSH..."
|
||
|
||
mkdir -p /root/.ssh
|
||
chmod 700 /root/.ssh
|
||
|
||
# Запрос данных VPS
|
||
echo -e "${BOLD}${YELLOW}════════════════════════════════════════════════════════════════${NC}"
|
||
echo -e "${BOLD}${YELLOW} НАСТРОЙКА ПОДКЛЮЧЕНИЯ К VPS ${NC}"
|
||
echo -e "${BOLD}${YELLOW}════════════════════════════════════════════════════════════════${NC}"
|
||
echo ""
|
||
|
||
local attempt=1
|
||
local max_attempts=3
|
||
while [ $attempt -le $max_attempts ]; do
|
||
echo -e "${CYAN}Попытка $attempt из $max_attempts:${NC}"
|
||
read -p "IP адрес или домен VPS: " VPS_HOST
|
||
read -p "Порт SSH (по умолчанию 22): " VPS_PORT
|
||
VPS_PORT=${VPS_PORT:-22}
|
||
echo -e "${CYAN}Выберите пользователя:${NC}"
|
||
echo "1) root"
|
||
echo "2) Другой"
|
||
read -p "Выбор [1-2]: " USER_CHOICE
|
||
if [ "$USER_CHOICE" == "1" ]; then
|
||
VPS_USER="root"
|
||
else
|
||
read -p "Имя пользователя: " VPS_USER
|
||
fi
|
||
|
||
if [ -z "$VPS_HOST" ] || [ -z "$VPS_USER" ]; then
|
||
echo -e "${RED}Обязательные поля не заполнены!${NC}"
|
||
attempt=$((attempt+1))
|
||
continue
|
||
fi
|
||
|
||
echo -e "${CYAN}Проверка данных:${NC}"
|
||
echo "VPS: $VPS_USER@$VPS_HOST:$VPS_PORT"
|
||
read -p "Верно? (y/n): " CONFIRM
|
||
if [[ $CONFIRM =~ ^[Yy]$ ]]; then
|
||
break
|
||
fi
|
||
attempt=$((attempt+1))
|
||
done
|
||
|
||
if [ $attempt -gt $max_attempts ]; then
|
||
echo -e "${RED}Превышено количество попыток. Выход.${NC}"
|
||
exit 1
|
||
fi
|
||
|
||
# Генерация ключа
|
||
if [ ! -f /root/.ssh/id_ed25519 ]; then
|
||
ssh-keygen -t ed25519 -N "" -f /root/.ssh/id_ed25519 -q
|
||
log_message "SSH ключ сгенерирован."
|
||
fi
|
||
|
||
# Конфиг SSH
|
||
cat > /root/.ssh/config << EOF
|
||
Host tunnel-vps
|
||
HostName $VPS_HOST
|
||
Port $VPS_PORT
|
||
User $VPS_USER
|
||
IdentityFile ~/.ssh/id_ed25519
|
||
StrictHostKeyChecking accept-new
|
||
ServerAliveInterval 30
|
||
ServerAliveCountMax 3
|
||
ExitOnForwardFailure yes
|
||
EOF
|
||
chmod 600 /root/.ssh/config
|
||
|
||
# Копирование ключа
|
||
read -s -p "Пароль для $VPS_USER@$VPS_HOST (Enter для пропуска): " VPS_PASSWORD
|
||
echo
|
||
if [ -n "$VPS_PASSWORD" ] && command -v sshpass &> /dev/null; then
|
||
sshpass -p "$VPS_PASSWORD" ssh-copy-id -i /root/.ssh/id_ed25519.pub "$VPS_USER@$VPS_HOST" -p "$VPS_PORT"
|
||
log_message "Ключ скопирован."
|
||
else
|
||
echo -e "${YELLOW}Скопируйте вручную: cat /root/.ssh/id_ed25519.pub${NC}"
|
||
read -p "Нажмите Enter после добавления на VPS..."
|
||
fi
|
||
|
||
# Тест подключения
|
||
if ssh -o BatchMode=yes "$VPS_USER@$VPS_HOST" -p "$VPS_PORT" echo "OK"; then
|
||
log_message "Подключение успешно."
|
||
else
|
||
echo -e "${RED}Подключение не удалось. Проверьте настройки.${NC}"
|
||
exit 1
|
||
fi
|
||
|
||
# Сохранение настроек
|
||
mkdir -p /etc/ssh_tunnel
|
||
cat > /etc/ssh_tunnel/vps_settings.conf << EOF
|
||
VPS_HOST="$VPS_HOST"
|
||
VPS_PORT="$VPS_PORT"
|
||
VPS_USER="$VPS_USER"
|
||
EOF
|
||
chmod 600 /etc/ssh_tunnel/vps_settings.conf
|
||
}
|
||
|
||
# Установка основного скрипта
|
||
install_main_script() {
|
||
log_message "Установка менеджера..."
|
||
mkdir -p /opt/ssh_tunnel_manager /var/log/ssh_tunnel
|
||
|
||
cat > /opt/ssh_tunnel_manager/manager.sh << 'EOF'
|
||
#!/bin/bash
|
||
|
||
# Автономный менеджер SSH туннелей
|
||
# Использование: tunnel-manager [команда]
|
||
|
||
source /etc/ssh_tunnel/vps_settings.conf 2>/dev/null || {
|
||
echo "Настройки VPS не найдены!"
|
||
exit 1
|
||
}
|
||
|
||
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'
|
||
|
||
CONFIG_DIR="/etc/ssh_tunnel"
|
||
LOG_DIR="/var/log/ssh_tunnel"
|
||
|
||
list_tunnels() {
|
||
echo -e "${CYAN}Активные туннели:${NC}"
|
||
systemctl list-units --type=service --all | grep ssh-tunnel || echo "Нет туннелей."
|
||
}
|
||
|
||
create_tunnel() {
|
||
read -p "Локальный порт: " LOCAL_PORT
|
||
read -p "Удаленный порт на VPS: " REMOTE_PORT
|
||
if [ -z "$LOCAL_PORT" ] || [ -z "$REMOTE_PORT" ]; then
|
||
echo -e "${RED}Поля обязательны.${NC}"
|
||
exit 1
|
||
fi
|
||
|
||
TUNNEL_ID="tunnel_${REMOTE_PORT}"
|
||
SERVICE_FILE="/etc/systemd/system/ssh-${TUNNEL_ID}.service"
|
||
|
||
cat > "$SERVICE_FILE" << EOSERVICE
|
||
[Unit]
|
||
Description=SSH Tunnel ${TUNNEL_ID}
|
||
After=network.target
|
||
|
||
[Service]
|
||
User=root
|
||
ExecStart=/usr/bin/autossh -M 0 -o "ServerAliveInterval 30" -o "ServerAliveCountMax 3" -NL *:${REMOTE_PORT}:localhost:${LOCAL_PORT} ${VPS_USER}@${VPS_HOST} -p ${VPS_PORT}
|
||
Restart=always
|
||
RestartSec=5
|
||
|
||
[Install]
|
||
WantedBy=multi-user.target
|
||
EOSERVICE
|
||
|
||
systemctl daemon-reload
|
||
systemctl enable ssh-${TUNNEL_ID}
|
||
systemctl start ssh-${TUNNEL_ID}
|
||
echo -e "${GREEN}Туннель создан.${NC}"
|
||
}
|
||
|
||
case "$1" in
|
||
list) list_tunnels ;;
|
||
create) create_tunnel ;;
|
||
*) echo "Использование: tunnel-manager [list|create]" ;;
|
||
esac
|
||
EOF
|
||
chmod +x /opt/ssh_tunnel_manager/manager.sh
|
||
ln -sf /opt/ssh_tunnel_manager/manager.sh /usr/local/bin/tunnel-manager
|
||
}
|
||
|
||
# Настройка монитора
|
||
setup_monitor() {
|
||
cat > /etc/systemd/system/tunnel-monitor.service << EOF
|
||
[Unit]
|
||
Description=Мониторинг SSH туннелей
|
||
After=network.target
|
||
|
||
[Service]
|
||
ExecStart=/opt/ssh_tunnel_manager/monitor.sh
|
||
Restart=always
|
||
|
||
[Install]
|
||
WantedBy=multi-user.target
|
||
EOF
|
||
|
||
cat > /opt/ssh_tunnel_manager/monitor.sh << 'EOF'
|
||
#!/bin/bash
|
||
|
||
while true; do
|
||
# Проверка и перезапуск туннелей
|
||
systemctl list-units --type=service | grep ssh-tunnel | while read service; do
|
||
if ! systemctl is-active $service; then
|
||
systemctl start $service
|
||
fi
|
||
done
|
||
sleep 60
|
||
done
|
||
EOF
|
||
chmod +x /opt/ssh_tunnel_manager/monitor.sh
|
||
|
||
systemctl daemon-reload
|
||
systemctl enable tunnel-monitor
|
||
systemctl start tunnel-monitor
|
||
}
|
||
|
||
# Пример туннеля
|
||
create_example_tunnel() {
|
||
source /etc/ssh_tunnel/vps_settings.conf
|
||
LOCAL_PORT=22
|
||
REMOTE_PORT=10022
|
||
TUNNEL_ID="example"
|
||
SERVICE_FILE="/etc/systemd/system/ssh-tunnel-${TUNNEL_ID}.service"
|
||
|
||
cat > "$SERVICE_FILE" << EOSERVICE
|
||
[Unit]
|
||
Description=Пример SSH туннеля
|
||
After=network.target
|
||
|
||
[Service]
|
||
User=root
|
||
ExecStart=/usr/bin/autossh -M 0 -o "ServerAliveInterval 30" -o "ServerAliveCountMax 3" -NR *:${REMOTE_PORT}:localhost:${LOCAL_PORT} ${VPS_USER}@${VPS_HOST} -p ${VPS_PORT}
|
||
Restart=always
|
||
RestartSec=5
|
||
|
||
[Install]
|
||
WantedBy=multi-user.target
|
||
EOSERVICE
|
||
|
||
systemctl daemon-reload
|
||
systemctl enable ssh-tunnel-${TUNNEL_ID}
|
||
systemctl start ssh-tunnel-${TUNNEL_ID}
|
||
echo -e "${GREEN}Пример туннеля создан (22 -> 10022).${NC}"
|
||
}
|
||
|
||
# Завершение
|
||
finish_installation() {
|
||
echo -e "${GREEN}Установка завершена!${NC}"
|
||
echo "Запустите tunnel-manager для управления."
|
||
log_message "Установка завершена."
|
||
}
|
||
|
||
install_dependencies
|
||
setup_ssh
|
||
install_main_script
|
||
setup_monitor
|
||
create_example_tunnel
|
||
finish_installation |