Files
vps_ssh_tunel/install_ssh_tunnel.sh
NW 49e5d7ccb7 v3.4
Добавлена функция check_and_configure_vps_sshd() - автоматически настраивает SSH сервер на VPS для:

        Многопользовательского доступа

        Одновременных подключений с нескольких мест

        Сохраняет аутентификацию по паролю (PasswordAuthentication yes)

        Добавляет аутентификацию по ключам

        Настраивает лимиты сессий (MaxSessions 20, MaxStartups 20:30:100)

        Включает поддержку туннелей

    Обновлена функция setup_vps() - теперь предлагает автоматическую настройку SSH на VPS после копирования ключа

    Добавлено новое меню "Настройки SSH Демона на VPS" (пункт 7) с опциями:

        Автоматическая настройка SSH сервера на VPS

        Ручная настройка (инструкции)

        Проверка текущих настроек на VPS

    Разделены настройки SSH демона:

        Пункт 7: Настройки SSH на VPS (удаленном сервере)

        Пункт 8: Настройки локального SSH демона

    Добавлена функция configure_vps_ssh_manually() - показывает подробные инструкции для ручной настройки VPS

    Обновлены конфигурации SSH - везде добавлены настройки для поддержки многопользовательского доступа:

        PasswordAuthentication yes

        PubkeyAuthentication yes

        MaxSessions 20

        MaxStartups 20:30:100
2025-12-22 21:17:41 +00:00

1742 lines
76 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 Tunnel Manager - Профессиональное решение для управления обратными SSH-туннелями
# Использует autossh и systemd для обеспечения стабильного и постоянного соединения.
#
# Использование:
# 1. Запуск одной командой (автоустановка + меню): curl -s https://.../install_ssh_tunnel.sh | sudo bash
# 2. Установка: sudo bash tunnel-manager.sh install
# 3. Запуск меню: sudo bash tunnel-manager.sh menu
#
# --- Глобальные переменные и конфигурация ---
CONFIG_DIR="/etc/tunnel-manager"
TUNNELS_DIR="$CONFIG_DIR/tunnels"
LOG_DIR="/var/log/tunnel-manager"
SERVICE_DIR="/etc/systemd/system"
SCRIPT_PATH="/usr/local/bin/tunnel-manager"
VPS_CONFIG="$CONFIG_DIR/vps_config"
# --- Цвета для вывода ---
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_message() {
local message="$1"
local color="${2:-$NC}"
local timestamp=$(date '+%Y-%m-%d %H:%M:%S')
# Вывод в консоль и запись в лог
echo -e "${color}[$timestamp] $message${NC}" | tee -a "$LOG_DIR/manager.log"
}
# Функция проверки ошибок
check_error() {
local exit_code=$?
if [ $exit_code -ne 0 ]; then
log_message "ОШИБКА (код $exit_code): $1" "$RED"
log_message "Подробности в логе: $LOG_DIR/manager.log" "$YELLOW"
echo -e "${YELLOW}Произошла ошибка: $1${NC}"
read -t 60 -p "Продолжить выполнение скрипта? (y/n): " -n 1 -r
echo
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
exit 1
fi
return 1
fi
return 0
}
# Функция проверки прав root
check_root() {
if [[ $EUID -ne 0 ]]; then
log_message "ОШИБКА: Этот скрипт требует прав root (sudo)." "$RED"
log_message "Пожалуйста, запустите: sudo bash $0 $1" "$BOLD"
exit 1
fi
}
# Функция безопасного ввода с ограничением попыток
safe_read() {
local prompt="$1"
local default="$2"
local var_name="$3"
local max_attempts="${4:-3}" # По умолчанию 3 попытки
local attempt=0
local input=""
while [[ $attempt -lt $max_attempts ]]; do
attempt=$((attempt + 1))
# Явное чтение из /dev/tty чтобы избежать проблем с pipe
if [[ -t 0 ]]; then
read -p "$prompt" input
else
read -p "$prompt" input </dev/tty
fi
input="${input:-$default}"
# Если есть ввод или значение по умолчанию
if [ -n "$input" ]; then
eval "$var_name=\"$input\""
return 0
# Если нет ввода и нет значения по умолчанию, и это не последняя попытка
elif [ -z "$default" ] && [[ $attempt -lt $max_attempts ]]; then
echo -e "${YELLOW}Поле не может быть пустым! Попытка $attempt из $max_attempts${NC}"
# Если нет ввода, но есть значение по умолчанию, и это не последняя попытка (должно быть обработано выше, но для надежности)
elif [ -n "$default" ]; then
eval "$var_name=\"$default\""
return 0
fi
done
# Если превышено количество попыток
echo -e "${RED}Превышено максимальное количество попыток ввода. Выход.${NC}"
exit 1
}
# Функция чтения ввода с поддержкой pipe
read_input() {
local prompt="$1"
local timeout="${2:-0}"
local input
if [[ -t 0 ]]; then
if [[ $timeout -gt 0 ]]; then
read -t "$timeout" -p "$prompt" input
else
read -p "$prompt" input
fi
else
# Если stdin не терминал (например, при pipe), читаем из /dev/tty
if [[ $timeout -gt 0 ]]; then
read -t "$timeout" -p "$prompt" input </dev/tty
else
read -p "$prompt" input </dev/tty
fi
fi
echo "$input"
}
# Функция чтения скрытого ввода (для паролей)
read_secret() {
local prompt="$1"
local secret
if [[ -t 0 ]]; then
read -s -p "$prompt" secret
echo
else
read -s -p "$prompt" secret </dev/tty
echo
fi
echo "$secret"
}
# Функция загрузки настроек VPS
load_vps_settings() {
if [ -f "$VPS_CONFIG" ]; then
source "$VPS_CONFIG"
return 0
fi
return 1
}
# Функция отображения публичного ключа
show_public_key() {
echo -e "${BOLD}${CYAN}--- Публичный ключ для копирования на VPS ---${NC}"
if [ -f "/root/.ssh/id_rsa.pub" ]; then
echo -e "${GREEN}Ключ RSA:${NC}"
cat /root/.ssh/id_rsa.pub
echo ""
else
echo -e "${RED}Публичный ключ не найден. Сначала выполните установку.${NC}"
fi
read_input "Нажмите Enter для продолжения..."
}
# Функция проверки SSH подключения с подробным выводом
check_ssh_connection() {
if ! load_vps_settings; then
log_message "Сначала необходимо настроить VPS (опция 1)." "$RED"
return 1
fi
echo -e "${CYAN}Проверка подключения к $VPS_USER@$VPS_HOST:$VPS_PORT...${NC}"
echo -e "${YELLOW}Используется ключ: /root/.ssh/id_rsa${NC}"
# Проверяем существование ключа
if [ ! -f "/root/.ssh/id_rsa" ]; then
echo -e "${RED}✗ SSH ключ не найден. Выполните установку менеджера.${NC}"
return 1
fi
# Проверяем права на ключ
if [ "$(stat -c %a /root/.ssh/id_rsa 2>/dev/null)" != "600" ]; then
echo -e "${YELLOW}⚠ Предупреждение: Неправильные права на ключ (должны быть 600)${NC}"
chmod 600 /root/.ssh/id_rsa 2>/dev/null
fi
# Выполняем тестовое подключение с подробным выводом
echo -e "${BLUE}Выполняем тестовую команду на удаленном сервере...${NC}"
if output=$(timeout 15 ssh -p "$VPS_PORT" \
-o BatchMode=yes \
-o ConnectTimeout=10 \
-o StrictHostKeyChecking=no \
-o UserKnownHostsFile=/dev/null \
-o IdentityFile=/root/.ssh/id_rsa \
"$VPS_USER@$VPS_HOST" "echo 'SSH Connection Test: SUCCESS'; whoami; hostname" 2>&1); then
echo -e "${GREEN}✓ SSH подключение работает!${NC}"
echo -e "${CYAN}Ответ от сервера:${NC}"
echo "$output"
return 0
else
echo -e "${RED}✗ SSH подключение не работает${NC}"
echo -e "${YELLOW}Возможные причины:${NC}"
echo "1. Ключ не скопирован на VPS"
echo "2. Порт $VPS_PORT закрыт на VPS"
echo "3. SSH сервер на VPS не запущен"
echo "4. Проблемы с сетью/файрволом"
echo "5. На VPS отключена аутентификация по паролю, а ключ не настроен"
echo ""
echo -e "${YELLOW}Проверьте:${NC}"
echo "1. Что ключ скопирован на VPS: ssh-copy-id -p $VPS_PORT $VPS_USER@$VPS_HOST"
echo "2. Что порт $VPS_PORT открыт: nc -zv $VPS_HOST $VPS_PORT"
echo "3. Что SSH сервер запущен на VPS"
echo "4. Что на VPS разрешена аутентификация по паролю (PasswordAuthentication yes)"
# Пробуем подключиться без ключа для диагностики
echo -e "\n${YELLOW}Проверка доступности порта...${NC}"
if timeout 3 nc -zv "$VPS_HOST" "$VPS_PORT" 2>&1; then
echo -e "${GREEN}✓ Порт $VPS_PORT доступен${NC}"
else
echo -e "${RED}✗ Порт $VPS_PORT недоступен${NC}"
fi
return 1
fi
}
# Функция проверки и настройки SSH сервера на VPS
check_and_configure_vps_sshd() {
if ! load_vps_settings; then
log_message "Сначала необходимо настроить VPS (опция 1)." "$RED"
return 1
fi
local VPS_PASSWORD="$1"
echo -e "${CYAN}Проверка и настройка SSH сервера на VPS...${NC}"
# Создаем временный скрипт для настройки VPS
local SETUP_SCRIPT="/tmp/setup_vps_sshd_$(date +%s).sh"
cat > "$SETUP_SCRIPT" << 'EOF_VPS_SETUP'
#!/bin/bash
# Настройка SSH сервера для поддержки многопользовательского доступа
# и работы туннелей с сохранением доступа по паролю
SSHD_CONFIG="/etc/ssh/sshd_config"
BACKUP_FILE="${SSHD_CONFIG}.backup.$(date +%Y%m%d%H%M%S)"
echo "=== Настройка SSH сервера на VPS ==="
echo "Создание резервной копии: $BACKUP_FILE"
cp "$SSHD_CONFIG" "$BACKUP_FILE"
echo "Настройка параметров SSH для туннелей и многопользовательского доступа..."
# Массив настроек, которые нужно применить
declare -A SSH_SETTINGS
SSH_SETTINGS=(
["PasswordAuthentication"]="yes"
["PubkeyAuthentication"]="yes"
["PermitRootLogin"]="yes"
["GatewayPorts"]="yes"
["AllowTcpForwarding"]="yes"
["PermitTunnel"]="yes"
["ClientAliveInterval"]="30"
["ClientAliveCountMax"]="3"
["MaxSessions"]="20"
["MaxStartups"]="20:30:100"
["TCPKeepAlive"]="yes"
["AllowStreamLocalForwarding"]="yes"
["X11Forwarding"]="yes"
["PrintMotd"]="no"
["PrintLastLog"]="yes"
["UsePAM"]="yes"
["UseDNS"]="no"
)
# Применяем настройки
for key in "${!SSH_SETTINGS[@]}"; do
value="${SSH_SETTINGS[$key]}"
# Проверяем существует ли настройка
if grep -q "^#\?\s*$key" "$SSHD_CONFIG"; then
# Заменяем существующую настройку
sed -i "s/^#\?\s*$key.*/$key $value/" "$SSHD_CONFIG"
echo "Обновлено: $key $value"
else
# Добавляем новую настройку
echo "$key $value" >> "$SSHD_CONFIG"
echo "Добавлено: $key $value"
fi
done
# Добавляем настройки для поддержки IPv4
if ! grep -q "^AddressFamily" "$SSHD_CONFIG"; then
echo "AddressFamily inet" >> "$SSHD_CONFIG"
echo "Добавлено: AddressFamily inet"
fi
# Проверяем конфигурацию
echo ""
echo "Проверка конфигурации SSH..."
if sshd -t; then
echo "✓ Конфигурация корректна"
# Перезапускаем SSH сервер
echo "Перезапуск SSH сервера..."
if systemctl restart sshd 2>/dev/null || service ssh restart 2>/dev/null || /etc/init.d/ssh restart 2>/dev/null; then
echo "✓ SSH сервер перезапущен"
echo ""
echo "=== НАСТРОЙКИ ВЫПОЛНЕНЫ ==="
echo "SSH сервер настроен для:"
echo " - Поддержки обратных туннелей"
echo " - Многопользовательского доступа"
echo " - Аутентификации по паролю И по ключам"
echo " - Одновременных подключений с нескольких IP"
echo ""
echo "Резервная копия: $BACKUP_FILE"
else
echo "✗ Не удалось перезапустить SSH сервер"
echo "Выполните вручную: systemctl restart sshd"
fi
else
echo "✗ Ошибка в конфигурации SSH"
echo "Восстановление из резервной копии..."
cp "$BACKUP_FILE" "$SSHD_CONFIG"
fi
EOF_VPS_SETUP
# Копируем скрипт на VPS и выполняем
echo "Копирование скрипта настройки на VPS..."
if [ -n "$VPS_PASSWORD" ]; then
# Используем sshpass для передачи пароля
if command -v sshpass &> /dev/null; then
# Копируем скрипт на VPS
if sshpass -p "$VPS_PASSWORD" scp -P "$VPS_PORT" -o StrictHostKeyChecking=no "$SETUP_SCRIPT" "$VPS_USER@$VPS_HOST:/tmp/setup_vps_sshd.sh" 2>/dev/null; then
echo "✓ Скрипт скопирован на VPS"
# Выполняем скрипт на VPS
echo "Выполнение настройки на VPS..."
if sshpass -p "$VPS_PASSWORD" ssh -p "$VPS_PORT" -o StrictHostKeyChecking=no "$VPS_USER@$VPS_HOST" "chmod +x /tmp/setup_vps_sshd.sh && sudo /tmp/setup_vps_sshd.sh" 2>&1; then
echo -e "${GREEN}✓ Настройка SSH сервера на VPS выполнена успешно${NC}"
else
echo -e "${YELLOW}Не удалось выполнить настройку автоматически${NC}"
echo -e "${YELLOW}Выполните настройку вручную на VPS${NC}"
fi
else
echo -e "${RED}Не удалось скопировать скрипт на VPS${NC}"
fi
else
echo -e "${YELLOW}⚠ sshpass не установлен. Невозможно автоматически настроить VPS${NC}"
fi
else
echo -e "${YELLOW}⚠ Пароль не указан. Невозможно автоматически настроить VPS${NC}"
echo -e "${YELLOW}Выполните настройку вручную:${NC}"
cat "$SETUP_SCRIPT"
fi
# Удаляем временный скрипт
rm -f "$SETUP_SCRIPT"
echo ""
echo -e "${CYAN}Рекомендуемые настройки для VPS (/etc/ssh/sshd_config):${NC}"
echo " PasswordAuthentication yes"
echo " PubkeyAuthentication yes"
echo " PermitRootLogin yes"
echo " MaxSessions 20"
echo " MaxStartups 20:30:100"
echo " GatewayPorts yes"
echo " AllowTcpForwarding yes"
echo ""
echo -e "${YELLOW}После изменения настроек перезапустите SSH сервер:${NC}"
echo " systemctl restart sshd"
}
# --- Основные функции ---
# 1. Установка зависимостей и настройка системы
install_manager() {
check_root "install"
log_message "Начало установки SSH Tunnel Manager..." "$CYAN"
# Создание директорий
log_message "Создание системных директорий..." "$BLUE"
mkdir -p "$CONFIG_DIR" "$TUNNELS_DIR" "$LOG_DIR"
chmod 700 "$CONFIG_DIR" "$TUNNELS_DIR"
chmod 777 "$LOG_DIR" # Для удобства логирования
# Установка зависимостей
log_message "Установка необходимых зависимостей (autossh, openssh-client)..." "$BLUE"
# Определение дистрибутива
local OS
if [ -f /etc/os-release ]; then
. /etc/os-release
OS=$ID
fi
log_message "Обнаружен дистрибутив: ${OS:-Unknown}" "$BLUE"
if [[ "$OS" == "ubuntu" || "$OS" == "debian" ]]; then
log_message "Обновление списка пакетов..." "$BLUE"
apt-get update 2>&1 | tee -a "$LOG_DIR/manager.log"
check_error "Не удалось обновить список пакетов"
log_message "Установка autossh, openssh-client и sshpass..." "$BLUE"
apt-get install -y autossh openssh-client sshpass netcat 2>&1 | tee -a "$LOG_DIR/manager.log"
check_error "Не удалось установить пакеты (apt)"
elif [[ "$OS" == "centos" || "$OS" == "rhel" || "$OS" == "fedora" || "$OS" == "rocky" || "$OS" == "almalinux" ]]; then
log_message "Установка autossh, openssh-clients и sshpass..." "$BLUE"
if command -v dnf &> /dev/null; then
dnf install -y autossh openssh-clients sshpass nc 2>&1 | tee -a "$LOG_DIR/manager.log"
check_error "Не удалось установить пакеты (dnf)"
else
yum install -y autossh openssh-clients sshpass nc 2>&1 | tee -a "$LOG_DIR/manager.log"
check_error "Не удалось установить пакеты (yum)"
fi
else
log_message "ОШИБКА: Не удалось определить менеджер пакетов (apt, dnf, yum)." "$RED"
log_message "Пожалуйста, установите autossh и openssh-client вручную." "$YELLOW"
return 1
fi
if ! command -v autossh &> /dev/null; then
log_message "ОШИБКА: autossh не установлен. Проверьте вывод установки." "$RED"
return 1
fi
log_message "Зависимости успешно установлены." "$GREEN"
# Копирование скрипта в системный путь
log_message "Копирование скрипта в $SCRIPT_PATH..." "$BLUE"
# Получаем путь к текущему скрипту
local SCRIPT_SOURCE
if [[ -f "$0" ]]; then
SCRIPT_SOURCE="$0"
else
# Если скрипт запущен через pipe, создаем временный файл
SCRIPT_SOURCE="/tmp/tunnel-manager-$(date +%s).sh"
cat > "$SCRIPT_SOURCE" << 'EOF'
# Скрипт будет заменен содержимым установщика
EOF
fi
# Копируем содержимое текущего скрипта
cat > "$SCRIPT_PATH" << 'EOFHDR'
#!/bin/bash
#
# SSH Tunnel Manager - Установленная версия
#
EOFHDR
# Добавляем основное содержимое скрипта
cat "$SCRIPT_SOURCE" >> "$SCRIPT_PATH"
chmod +x "$SCRIPT_PATH"
log_message "Установка завершена. Теперь можно использовать команду: sudo tunnel-manager menu" "$GREEN"
# Генерация SSH ключа
if [ ! -f "/root/.ssh/id_rsa" ]; then
log_message "Генерация SSH ключа RSA 4096 бит для root..." "$BLUE"
mkdir -p /root/.ssh
ssh-keygen -t rsa -b 4096 -N "" -f /root/.ssh/id_rsa -q
log_message "SSH ключ сгенерирован: /root/.ssh/id_rsa.pub" "$GREEN"
else
log_message "SSH ключ уже существует. Используем существующий." "$YELLOW"
fi
# Настройка SSH конфига для стабильности
log_message "Настройка SSH клиента для стабильности..." "$BLUE"
cat > /root/.ssh/config << EOFCONFIG
Host *
StrictHostKeyChecking no
UserKnownHostsFile /dev/null
ServerAliveInterval 30
ServerAliveCountMax 3
ConnectTimeout 30
TCPKeepAlive yes
IdentitiesOnly yes
ExitOnForwardFailure yes
ControlMaster auto
ControlPath ~/.ssh/control-%r@%h:%p
ControlPersist 10m
# Дополнительные настройки стабильности
IPQoS throughput
Compression yes
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
EOFCONFIG
chmod 600 /root/.ssh/config
log_message "Конфигурация SSH клиента обновлена." "$GREEN"
# Настройка локального SSHD
configure_local_sshd
}
# Функция установки SSH сервера
install_ssh_server() {
log_message "Проверка установки SSH сервера..." "$BLUE"
# Проверяем, установлен ли sshd
if ! command -v sshd &> /dev/null && [ ! -f /etc/ssh/sshd_config ]; then
log_message "SSH сервер не установлен. Устанавливаем..." "$YELLOW"
# Определение дистрибутива
local OS
if [ -f /etc/os-release ]; then
. /etc/os-release
OS=$ID
fi
if [[ "$OS" == "ubuntu" || "$OS" == "debian" ]]; then
apt-get install -y openssh-server 2>&1 | tee -a "$LOG_DIR/manager.log"
elif [[ "$OS" == "centos" || "$OS" == "rhel" || "$OS" == "fedora" || "$OS" == "rocky" || "$OS" == "almalinux" ]]; then
if command -v dnf &> /dev/null; then
dnf install -y openssh-server 2>&1 | tee -a "$LOG_DIR/manager.log"
else
yum install -y openssh-server 2>&1 | tee -a "$LOG_DIR/manager.log"
fi
else
log_message "Не удалось определить дистрибутив для установки SSH сервера." "$RED"
return 1
fi
# Проверяем установку
if command -v sshd &> /dev/null; then
log_message "SSH сервер успешно установлен." "$GREEN"
else
log_message "Не удалось установить SSH сервер." "$RED"
return 1
fi
else
log_message "SSH сервер уже установлен." "$GREEN"
fi
# Запускаем и включаем автозагрузку
if systemctl is-active sshd &> /dev/null; then
log_message "SSH сервер уже запущен." "$GREEN"
else
systemctl start sshd 2>&1 | tee -a "$LOG_DIR/manager.log"
systemctl enable sshd 2>&1 | tee -a "$LOG_DIR/manager.log"
log_message "SSH сервер запущен и включен в автозагрузку." "$GREEN"
fi
return 0
}
# Функция настройки локального SSH-демона для приема туннелей
configure_local_sshd() {
log_message "Настройка локального SSH-демона (sshd) для приема туннелей..." "$BLUE"
# Устанавливаем SSH сервер если нужно
install_ssh_server
local SSHD_CONFIG="/etc/ssh/sshd_config"
if [ ! -f "$SSHD_CONFIG" ]; then
log_message "ОШИБКА: Файл конфигурации SSHD не найден: $SSHD_CONFIG" "$RED"
log_message "Попытка найти альтернативный путь..." "$YELLOW"
# Пробуем найти sshd_config
SSHD_CONFIG=$(find /etc -name "sshd_config" 2>/dev/null | head -1)
if [ -z "$SSHD_CONFIG" ]; then
SSHD_CONFIG=$(find /etc/ssh -name "sshd_config" 2>/dev/null | head -1)
fi
if [ -z "$SSHD_CONFIG" ] || [ ! -f "$SSHD_CONFIG" ]; then
log_message "Не удалось найти файл конфигурации SSHD. Создаем новый." "$YELLOW"
mkdir -p /etc/ssh
SSHD_CONFIG="/etc/ssh/sshd_config"
# Создаем базовую конфигурацию
cat > "$SSHD_CONFIG" << 'EOFSSHD'
# SSH Server Configuration
Port 22
Protocol 2
HostKey /etc/ssh/ssh_host_rsa_key
HostKey /etc/ssh/ssh_host_ecdsa_key
HostKey /etc/ssh/ssh_host_ed25519_key
# Logging
SyslogFacility AUTH
LogLevel INFO
# Authentication:
LoginGraceTime 120
PermitRootLogin yes
StrictModes yes
PasswordAuthentication yes
PubkeyAuthentication yes
AuthenticationMethods publickey,password
# Allow forwardings for tunnels
AllowTcpForwarding yes
GatewayPorts yes
X11Forwarding yes
X11DisplayOffset 10
X11UseLocalhost yes
# Allow client to pass locale environment variables
AcceptEnv LANG LC_*
# Allow override in ~/.ssh/authorized_keys
AuthorizedKeysFile .ssh/authorized_keys
# Don't allow empty passwords
PermitEmptyPasswords no
# Change to no to disable s/key passwords
ChallengeResponseAuthentication no
# GSSAPI options
GSSAPIAuthentication no
GSSAPICleanupCredentials yes
UsePAM yes
# Allow client alive
ClientAliveInterval 30
ClientAliveCountMax 3
# Max sessions
MaxSessions 20
MaxStartups 20:30:100
# Allow tunnel creation
AllowStreamLocalForwarding yes
PermitTunnel yes
# Subsystem
Subsystem sftp /usr/lib/openssh/sftp-server
EOFSSHD
log_message "Создан базовый конфигурационный файл SSH сервера." "$GREEN"
fi
fi
# Создание резервной копии
cp "$SSHD_CONFIG" "${SSHD_CONFIG}.backup.$(date +%Y%m%d%H%M%S)"
log_message "Создана резервная копия: ${SSHD_CONFIG}.backup.$(date +%Y%m%d%H%M%S)" "$YELLOW"
# Настройки для приема обратных туннелей
log_message "Настройка параметров для SSH туннелей..." "$BLUE"
# Массив настроек
local SETTINGS=(
"GatewayPorts yes"
"AllowTcpForwarding yes"
"PermitTunnel yes"
"AllowStreamLocalForwarding yes"
"ClientAliveInterval 30"
"ClientAliveCountMax 3"
"TCPKeepAlive yes"
"PasswordAuthentication yes"
"PubkeyAuthentication yes"
"MaxSessions 20"
"MaxStartups 20:30:100"
)
# Применяем настройки
for setting in "${SETTINGS[@]}"; do
local key=$(echo "$setting" | awk '{print $1}')
local value=$(echo "$setting" | awk '{print $2}')
# Проверяем существует ли настройка
if grep -q "^#\?\s*$key" "$SSHD_CONFIG"; then
# Заменяем существующую настройку
sed -i "s/^#\?\s*$key.*/$setting/" "$SSHD_CONFIG"
log_message "Обновлено: $setting" "$GREEN"
else
# Добавляем новую настройку
echo "$setting" >> "$SSHD_CONFIG"
log_message "Добавлено: $setting" "$GREEN"
fi
done
# Проверяем и настраиваем PermitRootLogin
if ! grep -q "^PermitRootLogin" "$SSHD_CONFIG"; then
echo "PermitRootLogin yes" >> "$SSHD_CONFIG"
log_message "Добавлено: PermitRootLogin yes" "$GREEN"
fi
# Перезапуск SSHD
log_message "Перезапуск SSH демона..." "$BLUE"
if systemctl restart sshd 2>/dev/null || service ssh restart 2>/dev/null || /etc/init.d/ssh restart 2>/dev/null; then
log_message "SSHD перезапущен с новыми настройками." "$GREEN"
# Проверяем статус
if systemctl is-active sshd &> /dev/null || pgrep sshd &> /dev/null; then
log_message "SSH сервер успешно запущен." "$GREEN"
else
log_message "Предупреждение: Не удалось проверить статус SSH сервера." "$YELLOW"
fi
else
log_message "ПРЕДУПРЕЖДЕНИЕ: Не удалось перезапустить SSHD. Возможно, потребуется ручной перезапуск." "$YELLOW"
log_message "Выполните: systemctl restart sshd или service ssh restart" "$YELLOW"
fi
}
# 2. Настройка VPS (сервера) с автоматической настройкой SSH для многопользовательского доступа
setup_vps() {
check_root "setup_vps"
log_message "Настройка подключения к удаленному VPS (серверу)..." "$CYAN"
local current_host=""
local current_port="22"
local current_user=""
if load_vps_settings; then
current_host="$VPS_HOST"
current_port="$VPS_PORT"
current_user="$VPS_USER"
log_message "Текущая конфигурация: $current_user@$current_host:$current_port" "$YELLOW"
fi
echo -e "${BOLD}${CYAN}--- Настройка VPS ---${NC}"
echo -e "${YELLOW}Это настройка удаленного сервера (VPS), куда будут пробрасываться туннели${NC}"
echo ""
local VPS_HOST_TEMP
local VPS_PORT_TEMP
local VPS_USER_TEMP
local USER_CHOICE
# Ввод IP и Порта
safe_read "Введите IP адрес или доменное имя VPS (текущий: $current_host): " "$current_host" VPS_HOST_TEMP
safe_read "Введите порт SSH (по умолчанию 22, текущий: $current_port): " "$current_port" VPS_PORT_TEMP
# Выбор пользователя
echo -e "${CYAN}Выберите пользователя для подключения:${NC}"
echo "1) root (рекомендуется для полного доступа)"
echo "2) Другой пользователь"
USER_CHOICE=$(read_input "Ваш выбор [1-2]: ")
if [ "$USER_CHOICE" == "1" ]; then
VPS_USER_TEMP="root"
echo -e "${YELLOW}Будет использоваться пользователь: root${NC}"
else
safe_read "Введите имя пользователя на VPS (текущий: $current_user): " "$current_user" VPS_USER_TEMP
fi
VPS_HOST="$VPS_HOST_TEMP"
VPS_PORT="$VPS_PORT_TEMP"
VPS_USER="$VPS_USER_TEMP"
if [ -z "$VPS_HOST" ] || [ -z "$VPS_USER" ]; then
log_message "ОШИБКА: IP адрес и имя пользователя обязательны." "$RED"
read_input "Нажмите Enter для продолжения..."
return 1
fi
# Дополнительная проверка, если пользователь выбрал "Другой пользователь", но не ввел имя
if [ "$USER_CHOICE" == "2" ] && [ -z "$VPS_USER" ]; then
log_message "ОШИБКА: Имя пользователя обязательно." "$RED"
read_input "Нажмите Enter для продолжения..."
return 1
fi
# Сохранение настроек
cat > "$VPS_CONFIG" << 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 "$VPS_CONFIG"
log_message "Настройки VPS сохранены в $VPS_CONFIG" "$GREEN"
# Автоматическое копирование ключа
log_message "Попытка автоматического копирования SSH-ключа на VPS..." "$CYAN"
# Запрос пароля для sshpass с безопасным вводом
local VPS_PASSWORD
echo -e "${YELLOW}Для автоматического копирования ключа потребуется пароль от $VPS_USER на VPS.${NC}"
echo -e "${YELLOW}Если вы не хотите вводить пароль, нажмите Enter и скопируйте ключ вручную.${NC}"
# Используем read_secret для скрытого ввода
VPS_PASSWORD=$(read_secret "Введите пароль для $VPS_USER@$VPS_HOST (оставьте пустым для пропуска): ")
if [ -n "$VPS_PASSWORD" ]; then
if command -v sshpass &> /dev/null; then
# Используем sshpass для автоматического копирования ключа
echo -e "${BLUE}Копирую ключ на VPS...${NC}"
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_DIR/manager.log"; then
log_message "SSH ключ успешно скопирован на VPS!" "$GREEN"
# Предлагаем настроить SSH сервер на VPS для многопользовательского доступа
echo ""
echo -e "${CYAN}Настройка SSH сервера на VPS для поддержки:${NC}"
echo " - Многопользовательского доступа"
echo " - Одновременных подключений с нескольких мест"
echo " - Аутентификации по паролю И по ключам"
echo " - Обратных туннелей"
echo ""
CONFIGURE_VPS=$(read_input "Настроить SSH сервер на VPS автоматически? (y/N): ")
if [[ "$CONFIGURE_VPS" =~ ^[Yy]$ ]]; then
check_and_configure_vps_sshd "$VPS_PASSWORD"
else
echo -e "${YELLOW}Пропущена автоматическая настройка VPS${NC}"
echo -e "${YELLOW}Важно! Убедитесь, что на VPS в /etc/ssh/sshd_config есть:${NC}"
echo " PasswordAuthentication yes"
echo " MaxSessions 20"
echo " MaxStartups 20:30:100"
fi
else
log_message "ОШИБКА: Не удалось скопировать ключ через sshpass." "$RED"
log_message "Возможно, пароль неверен, или на VPS не установлен ssh-copy-id." "$YELLOW"
log_message "Вам может потребоваться скопировать ключ вручную:" "$YELLOW"
echo ""
cat /root/.ssh/id_rsa.pub
echo ""
echo -e "${YELLOW}Выполните на VPS команду:${NC}"
echo "mkdir -p ~/.ssh && echo '$(cat /root/.ssh/id_rsa.pub)' >> ~/.ssh/authorized_keys"
fi
else
log_message "ПРЕДУПРЕЖДЕНИЕ: sshpass не установлен. Невозможно скопировать ключ автоматически." "$YELLOW"
log_message "Вам потребуется скопировать ключ вручную:" "$YELLOW"
cat /root/.ssh/id_rsa.pub
fi
else
log_message "Пароль не введен. Вам потребуется скопировать ключ вручную:" "$YELLOW"
cat /root/.ssh/id_rsa.pub
fi
# Тестовое подключение
echo ""
log_message "Проверка подключения к $VPS_USER@$VPS_HOST:$VPS_PORT..." "$BLUE"
check_ssh_connection
read_input "Нажмите Enter для продолжения..."
}
# Функция для ручной настройки VPS SSH сервера
configure_vps_ssh_manually() {
echo -e "${BOLD}${CYAN}--- Ручная настройка SSH сервера на VPS ---${NC}"
echo ""
echo -e "${YELLOW}Для правильной работы туннелей и многопользовательского доступа,${NC}"
echo -e "${YELLOW}на VPS должны быть настроены следующие параметры в /etc/ssh/sshd_config:${NC}"
echo ""
echo -e "${GREEN}1. Разрешить аутентификацию по паролю:${NC}"
echo " PasswordAuthentication yes"
echo ""
echo -e "${GREEN}2. Разрешить аутентификацию по ключам:${NC}"
echo " PubkeyAuthentication yes"
echo ""
echo -e "${GREEN}3. Разрешить вход root:${NC}"
echo " PermitRootLogin yes"
echo ""
echo -e "${GREEN}4. Настройки для туннелей:${NC}"
echo " GatewayPorts yes"
echo " AllowTcpForwarding yes"
echo " PermitTunnel yes"
echo ""
echo -e "${GREEN}5. Настройки многопользовательского доступа:${NC}"
echo " MaxSessions 20"
echo " MaxStartups 20:30:100"
echo ""
echo -e "${GREEN}6. Дополнительные настройки:${NC}"
echo " ClientAliveInterval 30"
echo " ClientAliveCountMax 3"
echo " TCPKeepAlive yes"
echo ""
if load_vps_settings; then
echo -e "${CYAN}Ваш VPS: $VPS_USER@$VPS_HOST:$VPS_PORT${NC}"
echo ""
echo -e "${YELLOW}Команды для настройки VPS:${NC}"
echo "ssh -p $VPS_PORT $VPS_USER@$VPS_HOST"
echo ""
echo -e "${YELLOW}После подключения выполните на VPS:${NC}"
cat << 'EOF_VPS_COMMANDS'
# Создайте резервную копию конфигурации
sudo cp /etc/ssh/sshd_config /etc/ssh/sshd_config.backup
# Отредактируйте файл конфигурации
sudo nano /etc/ssh/sshd_config
# Добавьте или измените следующие параметры:
PasswordAuthentication yes
PubkeyAuthentication yes
PermitRootLogin yes
GatewayPorts yes
AllowTcpForwarding yes
PermitTunnel yes
MaxSessions 20
MaxStartups 20:30:100
ClientAliveInterval 30
ClientAliveCountMax 3
TCPKeepAlive yes
# После сохранения проверьте конфигурацию
sudo sshd -t
# Если проверка прошла успешно, перезапустите SSH сервер
sudo systemctl restart sshd
# Или для старых систем:
sudo service ssh restart
EOF_VPS_COMMANDS
else
echo -e "${RED}Сначала настройте VPS в основном меню (опция 1)${NC}"
fi
read_input "Нажмите Enter для продолжения..."
}
# 3. Добавление нового туннеля
add_tunnel() {
check_root "add_tunnel"
if ! load_vps_settings; then
log_message "Сначала необходимо настроить VPS (опция 1)." "$RED"
read_input "Нажмите Enter для продолжения..."
return 1
fi
echo -e "${BOLD}${CYAN}--- Добавление нового обратного туннеля (Local -> VPS) ---${NC}"
log_message "VPS: $VPS_USER@$VPS_HOST:$VPS_PORT" "$YELLOW"
echo -e "${YELLOW}Туннель будет пробрасывать локальный порт на этом компьютере через VPS${NC}"
echo ""
local LOCAL_PORT=""
local REMOTE_PORT=""
local TUNNEL_NAME=""
safe_read "Введите локальный порт, который нужно пробросить (например, 22 для SSH): " "" LOCAL_PORT
safe_read "Введите удаленный порт на VPS, через который будет доступен локальный порт (например, 10022): " "" REMOTE_PORT
safe_read "Введите имя туннеля (например, 'ssh_access'): " "" TUNNEL_NAME
# Проверка ввода
if ! [[ "$LOCAL_PORT" =~ ^[0-9]+$ ]] || [ "$LOCAL_PORT" -lt 1 ] || [ "$LOCAL_PORT" -gt 65535 ]; then
log_message "ОШИБКА: Локальный порт должен быть числом от 1 до 65535." "$RED"
read_input "Нажмите Enter для продолжения..."
return 1
fi
if ! [[ "$REMOTE_PORT" =~ ^[0-9]+$ ]] || [ "$REMOTE_PORT" -lt 1 ] || [ "$REMOTE_PORT" -gt 65535 ]; then
log_message "ОШИБКА: Удаленный порт должен быть числом от 1 до 65535." "$RED"
read_input "Нажмите Enter для продолжения..."
return 1
fi
if [ -z "$TUNNEL_NAME" ]; then
log_message "ОШИБКА: Имя туннеля обязательно." "$RED"
read_input "Нажмите Enter для продолжения..."
return 1
fi
# Проверка имени туннеля
TUNNEL_ID=$(echo "$TUNNEL_NAME" | tr '[:upper:]' '[:lower:]' | tr -cd '[:alnum:]_')
if [ -f "$TUNNELS_DIR/$TUNNEL_ID.conf" ]; then
log_message "ОШИБКА: Туннель с именем '$TUNNEL_ID' уже существует." "$RED"
read_input "Нажмите Enter для продолжения..."
return 1
fi
# Проверяем, доступен ли локальный порт
echo -e "${BLUE}Проверка доступности локального порта $LOCAL_PORT...${NC}"
if timeout 2 nc -z localhost "$LOCAL_PORT" 2>/dev/null; then
echo -e "${GREEN}✓ Локальный порт $LOCAL_PORT доступен${NC}"
else
echo -e "${YELLOW}⚠ Локальный порт $LOCAL_PORT не отвечает${NC}"
echo -e "${YELLOW}Убедитесь, что служба слушает на этом порту${NC}"
fi
# Создание конфигурационного файла туннеля
local CONFIG_FILE="$TUNNELS_DIR/$TUNNEL_ID.conf"
cat > "$CONFIG_FILE" << EOFCONF
# Конфигурация туннеля: $TUNNEL_NAME
TUNNEL_ID="$TUNNEL_ID"
TUNNEL_NAME="$TUNNEL_NAME"
LOCAL_PORT="$LOCAL_PORT"
REMOTE_PORT="$REMOTE_PORT"
VPS_HOST="$VPS_HOST"
VPS_PORT="$VPS_PORT"
VPS_USER="$VPS_USER"
CREATED="$(date '+%Y-%m-%d %H:%M:%S')"
EOFCONF
# Создание systemd unit-файла
local SERVICE_NAME="tunnel-$TUNNEL_ID"
local SERVICE_FILE="$SERVICE_DIR/$SERVICE_NAME.service"
cat > "$SERVICE_FILE" << EOFSERVICE
[Unit]
Description=SSH Reverse Tunnel: $TUNNEL_NAME ($LOCAL_PORT -> $REMOTE_PORT)
After=network-online.target
Wants=network-online.target
StartLimitIntervalSec=0
[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" \
-o "IdentityFile=/root/.ssh/id_rsa" \
-R $REMOTE_PORT:localhost:$LOCAL_PORT \
$VPS_USER@$VPS_HOST -p $VPS_PORT
ExecReload=/bin/kill -HUP \$MAINPID
Restart=always
RestartSec=10
User=root
StandardOutput=append:$LOG_DIR/$TUNNEL_ID.log
StandardError=append:$LOG_DIR/$TUNNEL_ID.log
[Install]
WantedBy=multi-user.target
EOFSERVICE
log_message "Конфигурация туннеля '$TUNNEL_NAME' создана." "$GREEN"
# Запуск и включение службы
systemctl daemon-reload
systemctl enable "$SERVICE_NAME.service" > /dev/null 2>&1
systemctl start "$SERVICE_NAME.service"
if systemctl is-active --quiet "$SERVICE_NAME.service"; then
log_message "Туннель '$TUNNEL_NAME' успешно запущен и включен в автозагрузку." "$GREEN"
echo ""
echo -e "${BOLD}${CYAN}Информация о туннеле:${NC}"
echo -e " Имя: $TUNNEL_NAME"
echo -e " Локальный порт: $LOCAL_PORT"
echo -e " Удаленный порт на VPS: $REMOTE_PORT"
echo -e " VPS: $VPS_USER@$VPS_HOST:$VPS_PORT"
echo ""
echo -e "${GREEN}Для доступа к локальному порту $LOCAL_PORT через VPS используйте:${NC}"
echo -e "${BOLD} ssh -p $REMOTE_PORT $VPS_USER@$VPS_HOST${NC}"
echo ""
echo -e "${YELLOW}Логи туннеля: $LOG_DIR/$TUNNEL_ID.log${NC}"
else
log_message "ОШИБКА: Не удалось запустить туннель '$TUNNEL_NAME'." "$RED"
log_message "Проверьте лог: tail -f $LOG_DIR/$TUNNEL_ID.log" "$YELLOW"
log_message "Проверьте подключение к VPS и права SSH ключа." "$YELLOW"
fi
read_input "Нажмите Enter для продолжения..."
}
# 4. Управление туннелем (запуск, остановка, перезапуск, удаление)
manage_tunnel() {
local TUNNEL_ID="$1"
local ACTION="$2"
local SERVICE_NAME="tunnel-$TUNNEL_ID"
if [ ! -f "$TUNNELS_DIR/$TUNNEL_ID.conf" ]; then
log_message "ОШИБКА: Туннель с ID '$TUNNEL_ID' не найден." "$RED"
return 1
fi
case "$ACTION" in
start|stop|restart)
systemctl "$ACTION" "$SERVICE_NAME.service"
log_message "Служба '$SERVICE_NAME' выполнила команду '$ACTION'." "$GREEN"
;;
status)
systemctl status "$SERVICE_NAME.service"
;;
remove)
log_message "Остановка и удаление туннеля '$TUNNEL_ID'..." "$YELLOW"
systemctl stop "$SERVICE_NAME.service"
systemctl disable "$SERVICE_NAME.service" > /dev/null 2>&1
rm -f "$SERVICE_DIR/$SERVICE_NAME.service"
rm -f "$TUNNELS_DIR/$TUNNEL_ID.conf"
rm -f "$LOG_DIR/$TUNNEL_ID.log"
systemctl daemon-reload
log_message "Туннель '$TUNNEL_ID' полностью удален." "$GREEN"
;;
*)
log_message "Неизвестное действие: $ACTION" "$RED"
return 1
;;
esac
}
# 5. Список туннелей
list_tunnels() {
echo -e "${BOLD}${CYAN}--- Список настроенных туннелей ---${NC}"
local count=0
local header="%-20s | %-10s | %-10s | %-20s | %-10s"
local separator="---------------------|------------|------------|----------------------|------------"
printf "$header\n" "ИМЯ ТУННЕЛЯ" "ЛОК. ПОРТ" "УД. ПОРТ" "СТАТУС" "АВТОЗАГРУЗКА"
echo "$separator"
for config_file in "$TUNNELS_DIR"/*.conf; do
if [ -f "$config_file" ]; then
source "$config_file"
local SERVICE_NAME="tunnel-$TUNNEL_ID"
local STATUS=$(systemctl is-active "$SERVICE_NAME.service" 2>/dev/null || echo "inactive")
local ENABLED=$(systemctl is-enabled "$SERVICE_NAME.service" 2>/dev/null || echo "disabled")
local STATUS_COLOR="$RED"
if [ "$STATUS" == "active" ]; then
STATUS_COLOR="$GREEN"
elif [ "$STATUS" == "inactive" ]; then
STATUS_COLOR="$YELLOW"
fi
printf "%-20s | %-10s | %-10s | ${STATUS_COLOR}%-20s${NC} | %-10s\n" \
"$TUNNEL_ID" "$LOCAL_PORT" "$REMOTE_PORT" "$STATUS" "$ENABLED"
count=$((count + 1))
fi
done
if [ "$count" -eq 0 ]; then
echo -e "${YELLOW}Туннели не найдены. Используйте опцию 2 для добавления нового.${NC}"
fi
echo ""
}
# Функция просмотра логов
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} Все логи туннелей (последние 5 строк)"
echo -e "${CYAN}[3]${NC} Системные логи (journalctl)"
echo -e "${CYAN}[4]${NC} Лог менеджера"
echo -e "${CYAN}[5]${NC} Назад"
echo ""
choice=$(read_input "Выберите действие: ")
case $choice in
1)
local LOG_DIR="/var/log/tunnel-manager"
echo -e "${CYAN}Доступные логи:${NC}"
ls -1 "$LOG_DIR"/*.log 2>/dev/null | xargs -n1 basename | grep -v "manager.log" || echo " Логи не найдены"
echo ""
log_file=$(read_input "Введите имя лог-файла (например, tunnel-ssh_access.log): ")
if [ -f "$LOG_DIR/$log_file" ]; then
less "$LOG_DIR/$log_file"
else
log_message "Файл не найден" "$RED"
sleep 1
fi
;;
2)
local LOG_DIR="/var/log/tunnel-manager"
echo -e "${CYAN}Все логи туннелей (последние 5 строк):${NC}"
for log in "$LOG_DIR"/tunnel-*.log; do
if [ -f "$log" ]; then
echo -e "\n${YELLOW}=== $(basename "$log") ===${NC}"
tail -5 "$log"
fi
done
read_input "Нажмите Enter для продолжения..."
;;
3)
echo -e "${CYAN}Системные логи туннелей (последний час):${NC}"
journalctl -u tunnel-* --since "1 hour ago" -n 20 2>/dev/null || log_message "Системные логи отсутствуют" "$YELLOW"
read_input "Нажмите Enter для продолжения..."
;;
4)
echo -e "${CYAN}Лог менеджера:${NC}"
less "/var/log/tunnel-manager/manager.log"
;;
5)
return
;;
*)
log_message "Неверный выбор" "$RED"
sleep 1
;;
esac
done
}
# Функция тестирования подключений
test_connections() {
while true; do
clear
echo -e "${BOLD}${CYAN}Тестирование подключений${NC}"
echo -e "${YELLOW}========================${NC}"
echo "1) Тест подключения к VPS"
echo "2) Тест локальных портов туннелей"
echo "3) Тест SSH ключа"
echo "4) Тест доступности портов на VPS"
echo "5) Назад"
echo ""
test_choice=$(read_input "Выберите тест: ")
case $test_choice in
1)
check_ssh_connection
read_input "Нажмите Enter для продолжения..."
;;
2)
echo -e "${CYAN}Тест локальных портов туннелей:${NC}"
local TUNNEL_DIR="/etc/tunnel-manager/tunnels"
local NC_CMD
if command -v nc &> /dev/null; then
NC_CMD="nc -z localhost"
elif command -v ncat &> /dev/null; then
NC_CMD="ncat -z localhost"
else
log_message "ОШИБКА: Утилита 'nc' или 'ncat' не найдена. Невозможно проверить порты." "$RED"
read_input "Нажмите Enter для продолжения..."
continue
fi
for conf in "$TUNNEL_DIR"/*.conf; do
if [ -f "$conf" ]; then
local LOCAL_PORT
LOCAL_PORT=$(grep '^LOCAL_PORT=' "$conf" | cut -d'=' -f2 | tr -d '"')
local TUNNEL_NAME
TUNNEL_NAME=$(basename "$conf" .conf)
echo -n " $TUNNEL_NAME (локальный порт $LOCAL_PORT): "
if timeout 2 $NC_CMD "$LOCAL_PORT" 2>/dev/null; then
echo -e "${GREEN}✓ Открыт${NC}"
else
echo -e "${RED}✗ Закрыт${NC}"
fi
fi
done
read_input "Нажмите Enter для продолжения..."
;;
3)
echo -e "${CYAN}Тест SSH ключа:${NC}"
if [ -f "/root/.ssh/id_rsa" ]; then
echo -e "${GREEN}✓ SSH ключ существует${NC}"
echo -e " Путь: /root/.ssh/id_rsa"
echo -e " Права: $(stat -c %a /root/.ssh/id_rsa 2>/dev/null || echo "неизвестно")"
if [ -f "/root/.ssh/id_rsa.pub" ]; then
echo -e "${GREEN}✓ Публичный ключ существует${NC}"
echo -e " Публичный ключ:"
head -c 100 /root/.ssh/id_rsa.pub
echo "..."
else
echo -e "${RED}✗ Публичный ключ не найден${NC}"
fi
else
echo -e "${RED}✗ SSH ключ не найден${NC}"
echo -e "${YELLOW}Выполните установку менеджера для генерации ключа${NC}"
fi
read_input "Нажмите Enter для продолжения..."
;;
4)
if load_vps_settings; then
echo -e "${CYAN}Тест доступности портов на VPS ($VPS_HOST):${NC}"
# Проверяем SSH порт
echo -n " SSH порт $VPS_PORT: "
if timeout 3 nc -zv "$VPS_HOST" "$VPS_PORT" 2>&1 | grep -q "succeeded"; then
echo -e "${GREEN}✓ Доступен${NC}"
else
echo -e "${RED}✗ Недоступен${NC}"
fi
# Проверяем порты туннелей
for conf in "$TUNNELS_DIR"/*.conf; do
if [ -f "$conf" ]; then
local REMOTE_PORT
REMOTE_PORT=$(grep '^REMOTE_PORT=' "$conf" | cut -d'=' -f2 | tr -d '"')
local TUNNEL_NAME
TUNNEL_NAME=$(basename "$conf" .conf)
echo -n " $TUNNEL_NAME (порт $REMOTE_PORT): "
if timeout 3 nc -zv "$VPS_HOST" "$REMOTE_PORT" 2>&1 | grep -q "succeeded"; then
echo -e "${GREEN}✓ Доступен${NC}"
else
echo -e "${RED}✗ Недоступен${NC}"
fi
fi
done
else
log_message "Сначала необходимо настроить VPS (опция 1)." "$RED"
fi
read_input "Нажмите Enter для продолжения..."
;;
5)
return
;;
*)
log_message "Неверный выбор" "$RED"
sleep 1
;;
esac
done
}
# Функция настройки маршрутизации (iptables)
setup_routing() {
if ! command -v iptables &> /dev/null; then
log_message "ОШИБКА: Утилита 'iptables' не найдена. Установите ее для использования этой функции." "$RED"
read_input "Нажмите Enter для продолжения..."
return
fi
while true; do
clear
echo -e "${BOLD}${CYAN}Настройка маршрутизации (iptables)${NC}"
echo -e "${YELLOW}==================================${NC}"
echo "1) Показать текущие правила NAT (PREROUTING)"
echo "2) Добавить правило перенаправления порта (DNAT)"
echo "3) Сохранить правила (требует iptables-persistent/netfilter-persistent)"
echo "4) Назад"
echo ""
routing_choice=$(read_input "Выберите действие: ")
case $routing_choice in
1)
echo -e "${CYAN}Текущие правила iptables (NAT PREROUTING):${NC}"
sudo iptables -t nat -L PREROUTING -n -v
read_input "Нажмите Enter для продолжения..."
;;
2)
IN_PORT=$(read_input "Входной порт (напр. 80): ")
DEST_IP=$(read_input "IP назначения (напр. 192.168.1.10): ")
DEST_PORT=$(read_input "Порт назначения (напр. 8080): ")
if [ -n "$IN_PORT" ] && [ -n "$DEST_IP" ] && [ -n "$DEST_PORT" ]; then
sudo iptables -t nat -A PREROUTING -p tcp --dport "$IN_PORT" -j DNAT --to-destination "$DEST_IP:$DEST_PORT"
log_message "Правило DNAT добавлено: $IN_PORT -> $DEST_IP:$DEST_PORT" "$GREEN"
else
log_message "Не все поля заполнены." "$RED"
fi
read_input "Нажмите Enter для продолжения..."
;;
3)
if command -v netfilter-persistent &> /dev/null; then
sudo netfilter-persistent save
log_message "Правила iptables сохранены с помощью netfilter-persistent." "$GREEN"
elif command -v iptables-save &> /dev/null; then
sudo mkdir -p /etc/iptables
sudo iptables-save > /etc/iptables/rules.v4
log_message "Правила iptables сохранены в /etc/iptables/rules.v4." "$GREEN"
else
log_message "ОШИБКА: Не найдена утилита для сохранения правил (netfilter-persistent или iptables-save)." "$RED"
fi
read_input "Нажмите Enter для продолжения..."
;;
4)
return
;;
*)
log_message "Неверный выбор" "$RED"
sleep 1
;;
esac
done
}
# Функция настройки SSH демона на VPS
setup_vps_ssh_config() {
while true; do
clear
echo -e "${BOLD}${CYAN}Настройки SSH Демона на VPS${NC}"
echo -e "${YELLOW}==============================${NC}"
if ! load_vps_settings; then
log_message "Сначала необходимо настроить VPS (опция 1)." "$RED"
read_input "Нажмите Enter для продолжения..."
return
fi
echo -e "${CYAN}VPS: $VPS_USER@$VPS_HOST:$VPS_PORT${NC}"
echo ""
echo "1) Автоматическая настройка SSH сервера на VPS"
echo "2) Ручная настройка SSH сервера на VPS (инструкции)"
echo "3) Проверить текущие настройки SSH на VPS"
echo "4) Назад"
echo ""
ssh_choice=$(read_input "Выберите действие: ")
case $ssh_choice in
1)
echo -e "${YELLOW}Для автоматической настройки потребуется пароль от VPS${NC}"
VPS_PASSWORD=$(read_secret "Введите пароль для $VPS_USER@$VPS_HOST: ")
if [ -n "$VPS_PASSWORD" ]; then
check_and_configure_vps_sshd "$VPS_PASSWORD"
else
echo -e "${RED}Пароль не введен. Невозможно выполнить автоматическую настройку.${NC}"
fi
read_input "Нажмите Enter для продолжения..."
;;
2)
configure_vps_ssh_manually
;;
3)
echo -e "${CYAN}Текущие настройки SSH на VPS:${NC}"
if [ -f "/root/.ssh/id_rsa" ]; then
ssh -p "$VPS_PORT" -i /root/.ssh/id_rsa -o BatchMode=yes "$VPS_USER@$VPS_HOST" \
"grep -E '^(PasswordAuthentication|PubkeyAuthentication|PermitRootLogin|GatewayPorts|AllowTcpForwarding|MaxSessions|MaxStartups)' /etc/ssh/sshd_config 2>/dev/null || echo 'Не удалось получить настройки'" 2>/dev/null
else
echo -e "${YELLOW}SSH ключ не найден. Сначала выполните установку.${NC}"
fi
read_input "Нажмите Enter для продолжения..."
;;
4)
return
;;
*)
log_message "Неверный выбор" "$RED"
sleep 1
;;
esac
done
}
# Функция настройки локального SSH демона
setup_local_ssh_config() {
while true; do
clear
echo -e "${BOLD}${CYAN}Настройки локального SSH Демона (sshd)${NC}"
echo -e "${YELLOW}====================================${NC}"
echo "1) Показать текущие настройки sshd (для туннелей)"
echo "2) Перезапустить SSH демон"
echo "3) Проверить конфигурацию sshd"
echo "4) Установить/переустановить SSH сервер"
echo "5) Настроить sshd для локальных подключений"
echo "6) Показать статус SSH сервера"
echo "7) Назад"
echo ""
ssh_choice=$(read_input "Выберите действие: ")
case $ssh_choice in
1)
echo -e "${CYAN}Текущие настройки sshd (GatewayPorts, AllowTcpForwarding):${NC}"
if [ -f "/etc/ssh/sshd_config" ]; then
grep -E "^(GatewayPorts|AllowTcpForwarding|PermitTunnel|AllowStreamLocalForwarding|PermitRootLogin|PasswordAuthentication)" /etc/ssh/sshd_config 2>/dev/null ||
echo "Настройки не найдены или файл конфигурации отсутствует"
else
echo "Файл /etc/ssh/sshd_config не найден"
echo "SSH сервер, вероятно, не установлен"
fi
read_input "Нажмите Enter для продолжения..."
;;
2)
if sudo systemctl restart sshd 2>/dev/null || sudo service ssh restart 2>/dev/null; then
log_message "SSH демон перезапущен." "$GREEN"
else
log_message "ОШИБКА: Не удалось перезапустить SSH демон." "$RED"
echo -e "${YELLOW}Попробуйте установить SSH сервер (опция 4)${NC}"
fi
read_input "Нажмите Enter для продолжения..."
;;
3)
if command -v sshd &> /dev/null; then
if sudo sshd -t 2>/dev/null; then
log_message "Конфигурация SSH корректна." "$GREEN"
else
log_message "ОШИБКА: Ошибка в конфигурации SSH." "$RED"
fi
else
log_message "SSH сервер не установлен." "$RED"
fi
read_input "Нажмите Enter для продолжения..."
;;
4)
install_ssh_server
read_input "Нажмите Enter для продолжения..."
;;
5)
configure_local_sshd
read_input "Нажмите Enter для продолжения..."
;;
6)
echo -e "${CYAN}Статус SSH сервера:${NC}"
if systemctl is-active sshd &> /dev/null; then
echo -e "${GREEN}✓ SSH сервер запущен${NC}"
systemctl status sshd --no-pager -l
elif pgrep sshd &> /dev/null; then
echo -e "${GREEN}✓ SSH процесс работает${NC}"
ps aux | grep sshd | grep -v grep
else
echo -e "${RED}✗ SSH сервер не запущен${NC}"
fi
read_input "Нажмите Enter для продолжения..."
;;
7)
return
;;
*)
log_message "Неверный выбор" "$RED"
sleep 1
;;
esac
done
}
# 6. Меню управления туннелями
manage_tunnels_menu() {
while true; do
clear
echo -e "${BOLD}${CYAN}--- Управление существующими туннелями ---${NC}"
echo -e "${YELLOW}===========================================${NC}"
local count=0
local TUNNEL_IDS=()
for config_file in "$TUNNELS_DIR"/*.conf; do
if [ -f "$config_file" ]; then
local TUNNEL_ID=$(basename "$config_file" .conf)
TUNNEL_IDS+=("$TUNNEL_ID")
count=$((count + 1))
fi
done
if [ "$count" -eq 0 ]; then
log_message "Туннели не найдены. Возврат в главное меню." "$YELLOW"
sleep 2
return
fi
list_tunnels
echo -e "${CYAN}Введите ID туннеля для управления (или 'b' для назад):${NC}"
TUNNEL_ID_MANAGE=$(read_input "ID туннеля: ")
if [ "$TUNNEL_ID_MANAGE" == "b" ]; then
return
fi
if [[ " ${TUNNEL_IDS[@]} " =~ " ${TUNNEL_ID_MANAGE} " ]]; then
while true; do
clear
echo -e "${BOLD}${CYAN}--- Управление туннелем $TUNNEL_ID_MANAGE ---${NC}"
echo -e "${YELLOW}===========================================${NC}"
# Загружаем конфигурацию туннеля
if [ -f "$TUNNELS_DIR/$TUNNEL_ID_MANAGE.conf" ]; then
source "$TUNNELS_DIR/$TUNNEL_ID_MANAGE.conf"
echo -e "${GREEN}Информация о туннеле:${NC}"
echo -e " Имя: $TUNNEL_NAME"
echo -e " Локальный порт: $LOCAL_PORT"
echo -e " Удаленный порт: $REMOTE_PORT"
echo -e " VPS: $VPS_USER@$VPS_HOST:$VPS_PORT"
echo -e " Создан: $CREATED"
echo ""
fi
# Показываем текущий статус
echo -e "${CYAN}Статус службы:${NC}"
manage_tunnel "$TUNNEL_ID_MANAGE" "status" | head -20
echo -e "\n${CYAN}Выберите действие:${NC}"
echo " s) Статус (обновить)"
echo " t) Старт"
echo " p) Стоп"
echo " r) Перезапуск"
echo " e) Включить автозагрузку"
echo " d) Отключить автозагрузку"
echo " x) Удалить"
echo " l) Просмотр логов"
echo " b) Назад"
ACTION_CHOICE=$(read_input "Действие: ")
case "$ACTION_CHOICE" in
s) ;; # Статус уже показан
t)
manage_tunnel "$TUNNEL_ID_MANAGE" "start"
sleep 2
;;
p)
manage_tunnel "$TUNNEL_ID_MANAGE" "stop"
sleep 2
;;
r)
manage_tunnel "$TUNNEL_ID_MANAGE" "restart"
sleep 2
;;
e)
systemctl enable "tunnel-$TUNNEL_ID_MANAGE.service" 2>/dev/null
log_message "Автозагрузка включена для туннеля $TUNNEL_ID_MANAGE" "$GREEN"
sleep 1
;;
d)
systemctl disable "tunnel-$TUNNEL_ID_MANAGE.service" 2>/dev/null
log_message "Автозагрузка отключена для туннеля $TUNNEL_ID_MANage" "$YELLOW"
sleep 1
;;
x)
CONFIRM_REMOVE=$(read_input "Вы уверены, что хотите удалить туннель $TUNNEL_ID_MANAGE? (y/N): ")
if [[ "$CONFIRM_REMOVE" =~ ^[Yy]$ ]]; then
manage_tunnel "$TUNNEL_ID_MANAGE" "remove"
sleep 2
return # Возврат в меню туннелей после удаления
fi
;;
l)
if [ -f "/var/log/tunnel-manager/$TUNNEL_ID_MANAGE.log" ]; then
less "/var/log/tunnel-manager/$TUNNEL_ID_MANAGE.log"
else
log_message "Лог файл не найден" "$RED"
sleep 1
fi
;;
b) break;;
*) log_message "Неизвестная опция." "$RED";;
esac
read_input "Нажмите Enter для продолжения...";
done
else
log_message "Туннель с ID '$TUNNEL_ID_MANAGE' не найден." "$RED"
sleep 1
fi
done
}
# 7. Главное меню
main_menu() {
check_root "menu"
while true; do
clear
echo -e "${BOLD}${CYAN}========================================================${NC}"
echo -e "${BOLD}${CYAN} SSH Tunnel Manager v2.0 (by Manus) ${NC}"
echo -e "${BOLD}${CYAN}========================================================${NC}"
# Проверяем наличие SSH ключа
if [ ! -f "/root/.ssh/id_rsa" ]; then
echo -e "${RED}⚠ SSH ключ не найден. Выполните установку.${NC}"
else
echo -e "${GREEN}✓ SSH ключ настроен${NC}"
fi
# Проверяем настройки VPS
if load_vps_settings; then
echo -e "${GREEN}✓ VPS настроен: $VPS_USER@$VPS_HOST:$VPS_PORT${NC}"
else
echo -e "${RED}✗ VPS не настроен. Начните с опции 1.${NC}"
fi
# Проверяем SSH сервер
if systemctl is-active sshd &> /dev/null || pgrep sshd &> /dev/null; then
echo -e "${GREEN}✓ SSH сервер запущен${NC}"
elif [ -f "/etc/ssh/sshd_config" ]; then
echo -e "${YELLOW}⚠ SSH сервер не запущен${NC}"
else
echo -e "${RED}✗ SSH сервер не установлен${NC}"
fi
echo ""
list_tunnels
echo -e "${BOLD}${YELLOW}--- МЕНЮ УПРАВЛЕНИЯ ---${NC}"
echo -e "1) ${BOLD}Настроить/сменить VPS${NC} (Указать адрес, пользователя, порт)"
echo -e "2) ${BOLD}Добавить новый туннель${NC} (Local:Port -> VPS:Port)"
echo -e "3) ${BOLD}Управление туннелем${NC} (Статус, Старт, Стоп, Перезапуск, Удаление)"
echo -e "4) ${BOLD}Просмотр логов и мониторинг${NC}"
echo -e "5) ${BOLD}Тестирование подключений${NC}"
echo -e "6) ${BOLD}Настройка маршрутизации (iptables)${NC}"
echo -e "7) ${BOLD}Настройки SSH Демона на VPS${NC} (Важно! Для многопользовательского доступа)"
echo -e "8) ${BOLD}Настройки локального SSH Демона${NC}"
echo -e "9) ${BOLD}Показать публичный ключ${NC} (Для копирования на VPS)"
echo -e "0) ${BOLD}Выход${NC}"
echo ""
choice=$(read_input "Выберите опцию [0-9]: ")
case $choice in
1) setup_vps ;;
2) add_tunnel ;;
3) manage_tunnels_menu ;;
4) view_logs ;;
5) test_connections ;;
6) setup_routing ;;
7) setup_vps_ssh_config ;;
8) setup_local_ssh_config ;;
9) show_public_key ;;
0)
log_message "Выход из менеджера." "$GREEN"
exit 0
;;
*)
log_message "Неверный выбор. Попробуйте еще раз." "$RED"
sleep 1
;;
esac
done
}
# --- Точка входа ---
# Главное изменение: если скрипт запущен без аргументов, выполняем автоматическую установку и запуск меню
if [[ $# -eq 0 ]]; then
echo -e "${BOLD}${CYAN}SSH Tunnel Manager v2.0${NC}"
echo -e "Автоматический запуск установки и меню..."
echo ""
# Проверяем, установлен ли уже скрипт
if [ -f "/usr/local/bin/tunnel-manager" ]; then
echo -e "${YELLOW}Менеджер уже установлен. Запуск меню...${NC}"
sleep 2
main_menu
else
echo -e "${GREEN}Начинаем установку...${NC}"
echo -e "${YELLOW}Установка займет несколько минут...${NC}"
sleep 2
install_manager
echo -e "${GREEN}Установка завершена. Запуск меню...${NC}"
sleep 2
main_menu
fi
else
case "$1" in
install)
install_manager
;;
menu)
main_menu
;;
*)
echo -e "${BOLD}${CYAN}SSH Tunnel Manager v2.0${NC}"
echo -e "Использование:"
echo -e " 1. Запуск одной командой (автоустановка + меню):"
echo -e " curl -s https://git.softuniq.eu/OpenDoor/vps_ssh_tunel/raw/branch/main/install_ssh_tunnel.sh | sudo bash"
echo -e " 2. Только установка: sudo bash $0 install"
echo -e " 3. Только меню: sudo bash $0 menu"
echo ""
echo -e "После установки можно использовать: sudo tunnel-manager menu"
;;
esac
fi
exit 0