Основные исправления и улучшения:

    Добавлена функция install_ssh_server() - автоматически устанавливает SSH сервер если он отсутствует.

    Улучшена функция configure_local_sshd():

        Автоматически устанавливает SSH сервер если нужно

        Создает базовый конфигурационный файл если он отсутствует

        Добавляет все необходимые настройки для работы туннелей

        Более надежная проверка и перезапуск службы

    Расширено меню настройки SSH демона (пункт 7):

        Добавлена опция установки SSH сервера

        Добавлена опция настройки sshd для локальных подключений

        Добавлена опция проверки статуса SSH сервера

    Улучшена функция проверки подключения check_ssh_connection():

        Более подробный вывод ошибок

        Проверка доступности порта

        Вывод полезной информации для диагностики

    Расширено тестирование подключений:

        Добавлен тест SSH ключа

        Добавлен тест доступности портов на VPS

    Исправлена установка скрипта - теперь корректно копируется даже при запуске через pipe.

    Добавлена проверка статусов в главное меню:

        Отображение статуса SSH ключа

        Отображение статуса SSH сервера

        Более информативный интерфейс

    Улучшено управление туннелями:

        Добавлены опции включения/отключения автозагрузки

        Добавлен просмотр логов конкретного туннеля

    Добавлена опция переустановки в главном меню.
This commit is contained in:
NW
2025-12-22 20:21:01 +00:00
parent d27e240e5e
commit bb20698de9

View File

@@ -109,6 +109,7 @@ safe_read() {
read_input() { read_input() {
local prompt="$1" local prompt="$1"
local timeout="${2:-0}" local timeout="${2:-0}"
local input
if [[ -t 0 ]]; then if [[ -t 0 ]]; then
if [[ $timeout -gt 0 ]]; then if [[ $timeout -gt 0 ]]; then
@@ -131,6 +132,8 @@ read_input() {
# Функция чтения скрытого ввода (для паролей) # Функция чтения скрытого ввода (для паролей)
read_secret() { read_secret() {
local prompt="$1" local prompt="$1"
local secret
if [[ -t 0 ]]; then if [[ -t 0 ]]; then
read -s -p "$prompt" secret read -s -p "$prompt" secret
echo echo
@@ -157,11 +160,13 @@ show_public_key() {
echo -e "${GREEN}Ключ RSA:${NC}" echo -e "${GREEN}Ключ RSA:${NC}"
cat /root/.ssh/id_rsa.pub cat /root/.ssh/id_rsa.pub
echo "" echo ""
else
echo -e "${RED}Публичный ключ не найден. Сначала выполните установку.${NC}"
fi fi
read_input "Нажмите Enter для продолжения..." read_input "Нажмите Enter для продолжения..."
} }
# Функция проверки SSH подключения # Функция проверки SSH подключения с подробным выводом
check_ssh_connection() { check_ssh_connection() {
if ! load_vps_settings; then if ! load_vps_settings; then
log_message "Сначала необходимо настроить VPS (опция 1)." "$RED" log_message "Сначала необходимо настроить VPS (опция 1)." "$RED"
@@ -169,11 +174,56 @@ check_ssh_connection() {
fi fi
echo -e "${CYAN}Проверка подключения к $VPS_USER@$VPS_HOST:$VPS_PORT...${NC}" echo -e "${CYAN}Проверка подключения к $VPS_USER@$VPS_HOST:$VPS_PORT...${NC}"
if timeout 10 ssh -p "$VPS_PORT" -o BatchMode=yes -o ConnectTimeout=5 "$VPS_USER@$VPS_HOST" "echo 'SSH Connection OK'" 2>/dev/null; then echo -e "${YELLOW}Используется ключ: /root/.ssh/id_rsa${NC}"
echo -e "${GREEN}✓ SSH подключение работает${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 return 0
else else
echo -e "${RED}✗ SSH подключение не работает${NC}" echo -e "${RED}✗ SSH подключение не работает${NC}"
echo -e "${YELLOW}Возможные причины:${NC}"
echo "1. Ключ не скопирован на VPS"
echo "2. Порт $VPS_PORT закрыт на VPS"
echo "3. SSH сервер на VPS не запущен"
echo "4. Проблемы с сетью/файрволом"
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 -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 return 1
fi fi
} }
@@ -208,15 +258,15 @@ install_manager() {
check_error "Не удалось обновить список пакетов" check_error "Не удалось обновить список пакетов"
log_message "Установка autossh, openssh-client и sshpass..." "$BLUE" log_message "Установка autossh, openssh-client и sshpass..." "$BLUE"
apt-get install -y autossh openssh-client sshpass 2>&1 | tee -a "$LOG_DIR/manager.log" apt-get install -y autossh openssh-client sshpass netcat 2>&1 | tee -a "$LOG_DIR/manager.log"
check_error "Не удалось установить пакеты (apt)" check_error "Не удалось установить пакеты (apt)"
elif [[ "$OS" == "centos" || "$OS" == "rhel" || "$OS" == "fedora" || "$OS" == "rocky" || "$OS" == "almalinux" ]]; then elif [[ "$OS" == "centos" || "$OS" == "rhel" || "$OS" == "fedora" || "$OS" == "rocky" || "$OS" == "almalinux" ]]; then
log_message "Установка autossh, openssh-clients и sshpass..." "$BLUE" log_message "Установка autossh, openssh-clients и sshpass..." "$BLUE"
if command -v dnf &> /dev/null; then if command -v dnf &> /dev/null; then
dnf install -y autossh openssh-clients sshpass 2>&1 | tee -a "$LOG_DIR/manager.log" dnf install -y autossh openssh-clients sshpass nc 2>&1 | tee -a "$LOG_DIR/manager.log"
check_error "Не удалось установить пакеты (dnf)" check_error "Не удалось установить пакеты (dnf)"
else else
yum install -y autossh openssh-clients sshpass 2>&1 | tee -a "$LOG_DIR/manager.log" yum install -y autossh openssh-clients sshpass nc 2>&1 | tee -a "$LOG_DIR/manager.log"
check_error "Не удалось установить пакеты (yum)" check_error "Не удалось установить пакеты (yum)"
fi fi
else else
@@ -233,8 +283,30 @@ install_manager() {
# Копирование скрипта в системный путь # Копирование скрипта в системный путь
log_message "Копирование скрипта в $SCRIPT_PATH..." "$BLUE" log_message "Копирование скрипта в $SCRIPT_PATH..." "$BLUE"
cp "$0" "$SCRIPT_PATH" # Получаем путь к текущему скрипту
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" chmod +x "$SCRIPT_PATH"
log_message "Установка завершена. Теперь можно использовать команду: sudo tunnel-manager menu" "$GREEN" log_message "Установка завершена. Теперь можно использовать команду: sudo tunnel-manager menu" "$GREEN"
# Генерация SSH ключа # Генерация SSH ключа
@@ -278,14 +350,141 @@ EOFCONFIG
configure_local_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-демона для приема туннелей # Функция настройки локального SSH-демона для приема туннелей
configure_local_sshd() { configure_local_sshd() {
log_message "Настройка локального SSH-демона (sshd) для приема туннелей..." "$BLUE" log_message "Настройка локального SSH-демона (sshd) для приема туннелей..." "$BLUE"
# Устанавливаем SSH сервер если нужно
install_ssh_server
local SSHD_CONFIG="/etc/ssh/sshd_config" local SSHD_CONFIG="/etc/ssh/sshd_config"
if [ ! -f "$SSHD_CONFIG" ]; then if [ ! -f "$SSHD_CONFIG" ]; then
log_message "ОШИБКА: Файл конфигурации SSHD не найден: $SSHD_CONFIG" "$RED" log_message "ОШИБКА: Файл конфигурации SSHD не найден: $SSHD_CONFIG" "$RED"
return 1 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
# 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 10
MaxStartups 10:30:100
# Allow tunnel creation
AllowStreamLocalForwarding yes
PermitTunnel yes
# Subsystem
Subsystem sftp /usr/lib/openssh/sftp-server
EOFSSHD
log_message "Создан базовый конфигурационный файл SSH сервера." "$GREEN"
fi
fi fi
# Создание резервной копии # Создание резервной копии
@@ -293,27 +492,56 @@ configure_local_sshd() {
log_message "Создана резервная копия: ${SSHD_CONFIG}.backup.$(date +%Y%m%d%H%M%S)" "$YELLOW" log_message "Создана резервная копия: ${SSHD_CONFIG}.backup.$(date +%Y%m%d%H%M%S)" "$YELLOW"
# Настройки для приема обратных туннелей # Настройки для приема обратных туннелей
log_message "Настройка параметров для SSH туннелей..." "$BLUE"
# Массив настроек
local SETTINGS=( local SETTINGS=(
"GatewayPorts yes" "GatewayPorts yes"
"AllowTcpForwarding yes" "AllowTcpForwarding yes"
"PermitTunnel yes"
"AllowStreamLocalForwarding yes"
"ClientAliveInterval 30"
"ClientAliveCountMax 3"
"TCPKeepAlive yes"
) )
# Применяем настройки
for setting in "${SETTINGS[@]}"; do for setting in "${SETTINGS[@]}"; do
key=$(echo "$setting" | cut -d' ' -f1) local key=$(echo "$setting" | awk '{print $1}')
local value=$(echo "$setting" | awk '{print $2}')
# Проверяем существует ли настройка
if grep -q "^#\?\s*$key" "$SSHD_CONFIG"; then if grep -q "^#\?\s*$key" "$SSHD_CONFIG"; then
# Заменяем или раскомментируем # Заменяем существующую настройку
sed -i "s/^#\?\s*$key.*/$setting/" "$SSHD_CONFIG" sed -i "s/^#\?\s*$key.*/$setting/" "$SSHD_CONFIG"
log_message "Обновлено: $setting" "$GREEN"
else else
# Добавляем в конец файла # Добавляем новую настройку
echo "$setting" >> "$SSHD_CONFIG" echo "$setting" >> "$SSHD_CONFIG"
log_message "Добавлено: $setting" "$GREEN"
fi fi
done done
# Проверяем и настраиваем PermitRootLogin
if ! grep -q "^PermitRootLogin" "$SSHD_CONFIG"; then
echo "PermitRootLogin yes" >> "$SSHD_CONFIG"
log_message "Добавлено: PermitRootLogin yes" "$GREEN"
fi
# Перезапуск SSHD # Перезапуск SSHD
if systemctl restart sshd 2>/dev/null || service ssh restart 2>/dev/null; then log_message "Перезапуск SSH демона..." "$BLUE"
log_message "SSHD перезапущен с новыми настройками (GatewayPorts, AllowTcpForwarding)." "$GREEN" 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 else
log_message "ПРЕДУПРЕЖДЕНИЕ: Не удалось перезапустить SSHD. Возможно, потребуется ручной перезапуск." "$YELLOW" log_message "ПРЕДУПРЕЖДЕНИЕ: Не удалось перезапустить SSHD. Возможно, потребуется ручной перезапуск." "$YELLOW"
log_message "Выполните: systemctl restart sshd или service ssh restart" "$YELLOW"
fi fi
} }
@@ -334,6 +562,8 @@ setup_vps() {
fi fi
echo -e "${BOLD}${CYAN}--- Настройка VPS ---${NC}" echo -e "${BOLD}${CYAN}--- Настройка VPS ---${NC}"
echo -e "${YELLOW}Это настройка удаленного сервера (VPS), куда будут пробрасываться туннели${NC}"
echo ""
local VPS_HOST_TEMP local VPS_HOST_TEMP
local VPS_PORT_TEMP local VPS_PORT_TEMP
@@ -364,12 +594,14 @@ setup_vps() {
if [ -z "$VPS_HOST" ] || [ -z "$VPS_USER" ]; then if [ -z "$VPS_HOST" ] || [ -z "$VPS_USER" ]; then
log_message "ОШИБКА: IP адрес и имя пользователя обязательны." "$RED" log_message "ОШИБКА: IP адрес и имя пользователя обязательны." "$RED"
read_input "Нажмите Enter для продолжения..."
return 1 return 1
fi fi
# Дополнительная проверка, если пользователь выбрал "Другой пользователь", но не ввел имя # Дополнительная проверка, если пользователь выбрал "Другой пользователь", но не ввел имя
if [ "$USER_CHOICE" == "2" ] && [ -z "$VPS_USER" ]; then if [ "$USER_CHOICE" == "2" ] && [ -z "$VPS_USER" ]; then
log_message "ОШИБКА: Имя пользователя обязательно." "$RED" log_message "ОШИБКА: Имя пользователя обязательно." "$RED"
read_input "Нажмите Enter для продолжения..."
return 1 return 1
fi fi
@@ -390,20 +622,26 @@ EOFSETTINGS
# Запрос пароля для sshpass с безопасным вводом # Запрос пароля для sshpass с безопасным вводом
local VPS_PASSWORD local VPS_PASSWORD
echo -e "${YELLOW}Для автоматического копирования ключа потребуется пароль от $VPS_USER на VPS.${NC}" echo -e "${YELLOW}Для автоматического копирования ключа потребуется пароль от $VPS_USER на VPS.${NC}"
echo -e "${YELLOW}Если вы не хотите вводить пароль, нажмите Enter и скопируйте ключ вручную.${NC}"
# Используем read_secret для скрытого ввода # Используем read_secret для скрытого ввода
VPS_PASSWORD=$(read_secret "Введите пароль для $VPS_USER@$VPS_HOST: ") VPS_PASSWORD=$(read_secret "Введите пароль для $VPS_USER@$VPS_HOST (оставьте пустым для пропуска): ")
if [ -n "$VPS_PASSWORD" ]; then if [ -n "$VPS_PASSWORD" ]; then
if command -v sshpass &> /dev/null; then if command -v sshpass &> /dev/null; then
# Используем sshpass для автоматического копирования ключа # Используем 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 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" log_message "SSH ключ успешно скопирован на VPS!" "$GREEN"
else else
log_message "ОШИБКА: Не удалось скопировать ключ через sshpass." "$RED" log_message "ОШИБКА: Не удалось скопировать ключ через sshpass." "$RED"
log_message "Возможно, пароль неверен, или на VPS не установлен ssh-copy-id." "$YELLOW" log_message "Возможно, пароль неверен, или на VPS не установлен ssh-copy-id." "$YELLOW"
log_message "Вам может потребоваться скопировать ключ вручную:" "$YELLOW" log_message "Вам может потребоваться скопировать ключ вручную:" "$YELLOW"
echo ""
cat /root/.ssh/id_rsa.pub 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 fi
else else
log_message "ПРЕДУПРЕЖДЕНИЕ: sshpass не установлен. Невозможно скопировать ключ автоматически." "$YELLOW" log_message "ПРЕДУПРЕЖДЕНИЕ: sshpass не установлен. Невозможно скопировать ключ автоматически." "$YELLOW"
@@ -416,13 +654,9 @@ EOFSETTINGS
fi fi
# Тестовое подключение # Тестовое подключение
echo ""
log_message "Проверка подключения к $VPS_USER@$VPS_HOST:$VPS_PORT..." "$BLUE" log_message "Проверка подключения к $VPS_USER@$VPS_HOST:$VPS_PORT..." "$BLUE"
if timeout 10 ssh -p "$VPS_PORT" -o BatchMode=yes "$VPS_USER@$VPS_HOST" "echo 'Connection OK'" 2>/dev/null; then check_ssh_connection
log_message "Тестовое подключение успешно! Ключ работает." "$GREEN"
else
log_message "ОШИБКА: Тестовое подключение не удалось." "$RED"
log_message "Убедитесь, что публичный ключ скопирован, порт $VPS_PORT открыт, и SSH-сервер на VPS запущен." "$YELLOW"
fi
read_input "Нажмите Enter для продолжения..." read_input "Нажмите Enter для продолжения..."
} }
@@ -438,6 +672,8 @@ add_tunnel() {
echo -e "${BOLD}${CYAN}--- Добавление нового обратного туннеля (Local -> VPS) ---${NC}" echo -e "${BOLD}${CYAN}--- Добавление нового обратного туннеля (Local -> VPS) ---${NC}"
log_message "VPS: $VPS_USER@$VPS_HOST:$VPS_PORT" "$YELLOW" log_message "VPS: $VPS_USER@$VPS_HOST:$VPS_PORT" "$YELLOW"
echo -e "${YELLOW}Туннель будет пробрасывать локальный порт на этом компьютере через VPS${NC}"
echo ""
local LOCAL_PORT="" local LOCAL_PORT=""
local REMOTE_PORT="" local REMOTE_PORT=""
@@ -447,8 +683,21 @@ add_tunnel() {
safe_read "Введите удаленный порт на VPS, через который будет доступен локальный порт (например, 10022): " "" REMOTE_PORT safe_read "Введите удаленный порт на VPS, через который будет доступен локальный порт (например, 10022): " "" REMOTE_PORT
safe_read "Введите имя туннеля (например, 'ssh_access'): " "" TUNNEL_NAME safe_read "Введите имя туннеля (например, 'ssh_access'): " "" TUNNEL_NAME
if [ -z "$LOCAL_PORT" ] || [ -z "$REMOTE_PORT" ] || [ -z "$TUNNEL_NAME" ]; then # Проверка ввода
log_message "ОШИБКА: Все поля обязательны." "$RED" 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 для продолжения..." read_input "Нажмите Enter для продолжения..."
return 1 return 1
fi fi
@@ -461,11 +710,21 @@ add_tunnel() {
return 1 return 1
fi 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" local CONFIG_FILE="$TUNNELS_DIR/$TUNNEL_ID.conf"
cat > "$CONFIG_FILE" << EOFCONF cat > "$CONFIG_FILE" << EOFCONF
# Конфигурация туннеля: $TUNNEL_NAME # Конфигурация туннеля: $TUNNEL_NAME
TUNNEL_ID="$TUNNEL_ID" TUNNEL_ID="$TUNNEL_ID"
TUNNEL_NAME="$TUNNEL_NAME"
LOCAL_PORT="$LOCAL_PORT" LOCAL_PORT="$LOCAL_PORT"
REMOTE_PORT="$REMOTE_PORT" REMOTE_PORT="$REMOTE_PORT"
VPS_HOST="$VPS_HOST" VPS_HOST="$VPS_HOST"
@@ -483,6 +742,7 @@ EOFCONF
Description=SSH Reverse Tunnel: $TUNNEL_NAME ($LOCAL_PORT -> $REMOTE_PORT) Description=SSH Reverse Tunnel: $TUNNEL_NAME ($LOCAL_PORT -> $REMOTE_PORT)
After=network-online.target After=network-online.target
Wants=network-online.target Wants=network-online.target
StartLimitIntervalSec=0
[Service] [Service]
Type=simple Type=simple
@@ -498,6 +758,7 @@ ExecStart=/usr/bin/autossh -M 0 -N \
-o "IdentityFile=/root/.ssh/id_rsa" \ -o "IdentityFile=/root/.ssh/id_rsa" \
-R $REMOTE_PORT:localhost:$LOCAL_PORT \ -R $REMOTE_PORT:localhost:$LOCAL_PORT \
$VPS_USER@$VPS_HOST -p $VPS_PORT $VPS_USER@$VPS_HOST -p $VPS_PORT
ExecReload=/bin/kill -HUP \$MAINPID
Restart=always Restart=always
RestartSec=10 RestartSec=10
User=root User=root
@@ -517,11 +778,21 @@ EOFSERVICE
if systemctl is-active --quiet "$SERVICE_NAME.service"; then if systemctl is-active --quiet "$SERVICE_NAME.service"; then
log_message "Туннель '$TUNNEL_NAME' успешно запущен и включен в автозагрузку." "$GREEN" log_message "Туннель '$TUNNEL_NAME' успешно запущен и включен в автозагрузку." "$GREEN"
log_message "Для доступа к локальному порту $LOCAL_PORT через VPS используйте:" "$YELLOW" echo ""
log_message "ssh -p $REMOTE_PORT $VPS_USER@$VPS_HOST" "$BOLD" 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 else
log_message "ОШИБКА: Не удалось запустить туннель '$TUNNEL_NAME'." "$RED" log_message "ОШИБКА: Не удалось запустить туннель '$TUNNEL_NAME'." "$RED"
log_message "Проверьте лог: tail -f $LOG_DIR/$TUNNEL_ID.log" "$YELLOW" log_message "Проверьте лог: tail -f $LOG_DIR/$TUNNEL_ID.log" "$YELLOW"
log_message "Проверьте подключение к VPS и права SSH ключа." "$YELLOW"
fi fi
read_input "Нажмите Enter для продолжения..." read_input "Нажмите Enter для продолжения..."
@@ -610,7 +881,8 @@ view_logs() {
echo -e "${CYAN}[1]${NC} Логи конкретного туннеля" echo -e "${CYAN}[1]${NC} Логи конкретного туннеля"
echo -e "${CYAN}[2]${NC} Все логи туннелей (последние 5 строк)" echo -e "${CYAN}[2]${NC} Все логи туннелей (последние 5 строк)"
echo -e "${CYAN}[3]${NC} Системные логи (journalctl)" echo -e "${CYAN}[3]${NC} Системные логи (journalctl)"
echo -e "${CYAN}[4]${NC} Назад" echo -e "${CYAN}[4]${NC} Лог менеджера"
echo -e "${CYAN}[5]${NC} Назад"
echo "" echo ""
choice=$(read_input "Выберите действие: ") choice=$(read_input "Выберите действие: ")
@@ -619,7 +891,7 @@ view_logs() {
1) 1)
local LOG_DIR="/var/log/tunnel-manager" local LOG_DIR="/var/log/tunnel-manager"
echo -e "${CYAN}Доступные логи:${NC}" echo -e "${CYAN}Доступные логи:${NC}"
find "$LOG_DIR" -maxdepth 1 -type f -name "tunnel-*.log" -printf " %f\n" ls -1 "$LOG_DIR"/*.log 2>/dev/null | xargs -n1 basename | grep -v "manager.log" || echo " Логи не найдены"
echo "" echo ""
log_file=$(read_input "Введите имя лог-файла (например, tunnel-ssh_access.log): ") log_file=$(read_input "Введите имя лог-файла (например, tunnel-ssh_access.log): ")
if [ -f "$LOG_DIR/$log_file" ]; then if [ -f "$LOG_DIR/$log_file" ]; then
@@ -646,6 +918,10 @@ view_logs() {
read_input "Нажмите Enter для продолжения..." read_input "Нажмите Enter для продолжения..."
;; ;;
4) 4)
echo -e "${CYAN}Лог менеджера:${NC}"
less "/var/log/tunnel-manager/manager.log"
;;
5)
return return
;; ;;
*) *)
@@ -664,7 +940,9 @@ test_connections() {
echo -e "${YELLOW}========================${NC}" echo -e "${YELLOW}========================${NC}"
echo "1) Тест подключения к VPS" echo "1) Тест подключения к VPS"
echo "2) Тест локальных портов туннелей" echo "2) Тест локальных портов туннелей"
echo "3) Назад" echo "3) Тест SSH ключа"
echo "4) Тест доступности портов на VPS"
echo "5) Назад"
echo "" echo ""
test_choice=$(read_input "Выберите тест: ") test_choice=$(read_input "Выберите тест: ")
@@ -706,6 +984,60 @@ test_connections() {
read_input "Нажмите Enter для продолжения..." read_input "Нажмите Enter для продолжения..."
;; ;;
3) 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 return
;; ;;
*) *)
@@ -788,7 +1120,10 @@ setup_ssh_config() {
echo "1) Показать текущие настройки sshd (для туннелей)" echo "1) Показать текущие настройки sshd (для туннелей)"
echo "2) Перезапустить SSH демон" echo "2) Перезапустить SSH демон"
echo "3) Проверить конфигурацию sshd" echo "3) Проверить конфигурацию sshd"
echo "4) Назад" echo "4) Установить/переустановить SSH сервер"
echo "5) Настроить sshd для локальных подключений"
echo "6) Показать статус SSH сервера"
echo "7) Назад"
echo "" echo ""
ssh_choice=$(read_input "Выберите действие: ") ssh_choice=$(read_input "Выберите действие: ")
@@ -796,7 +1131,13 @@ setup_ssh_config() {
case $ssh_choice in case $ssh_choice in
1) 1)
echo -e "${CYAN}Текущие настройки sshd (GatewayPorts, AllowTcpForwarding):${NC}" echo -e "${CYAN}Текущие настройки sshd (GatewayPorts, AllowTcpForwarding):${NC}"
grep -E "^(GatewayPorts|AllowTcpForwarding)" /etc/ssh/sshd_config 2>/dev/null || log_message "Настройки не найдены" "$YELLOW" if [ -f "/etc/ssh/sshd_config" ]; then
grep -E "^(GatewayPorts|AllowTcpForwarding|PermitTunnel|AllowStreamLocalForwarding|PermitRootLogin)" /etc/ssh/sshd_config 2>/dev/null ||
echo "Настройки не найдены или файл конфигурации отсутствует"
else
echo "Файл /etc/ssh/sshd_config не найден"
echo "SSH сервер, вероятно, не установлен"
fi
read_input "Нажмите Enter для продолжения..." read_input "Нажмите Enter для продолжения..."
;; ;;
2) 2)
@@ -804,18 +1145,44 @@ setup_ssh_config() {
log_message "SSH демон перезапущен." "$GREEN" log_message "SSH демон перезапущен." "$GREEN"
else else
log_message "ОШИБКА: Не удалось перезапустить SSH демон." "$RED" log_message "ОШИБКА: Не удалось перезапустить SSH демон." "$RED"
echo -e "${YELLOW}Попробуйте установить SSH сервер (опция 4)${NC}"
fi fi
read_input "Нажмите Enter для продолжения..." read_input "Нажмите Enter для продолжения..."
;; ;;
3) 3)
if sudo sshd -t 2>/dev/null; then if command -v sshd &> /dev/null; then
log_message "Конфигурация SSH корректна." "$GREEN" if sudo sshd -t 2>/dev/null; then
log_message "Конфигурация SSH корректна." "$GREEN"
else
log_message "ОШИБКА: Ошибка в конфигурации SSH." "$RED"
fi
else else
log_message "ОШИБКА: Ошибка в конфигурации SSH." "$RED" log_message "SSH сервер не установлен." "$RED"
fi fi
read_input "Нажмите Enter для продолжения..." read_input "Нажмите Enter для продолжения..."
;; ;;
4) 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 return
;; ;;
*) *)
@@ -865,31 +1232,75 @@ manage_tunnels_menu() {
echo -e "${BOLD}${CYAN}--- Управление туннелем $TUNNEL_ID_MANAGE ---${NC}" echo -e "${BOLD}${CYAN}--- Управление туннелем $TUNNEL_ID_MANAGE ---${NC}"
echo -e "${YELLOW}===========================================${NC}" echo -e "${YELLOW}===========================================${NC}"
# Показать текущий статус # Загружаем конфигурацию туннеля
manage_tunnel "$TUNNEL_ID_MANAGE" "status" 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 -e "\n${CYAN}Выберите действие:${NC}"
echo " s) Статус (обновить)" echo " s) Статус (обновить)"
echo " t) Старт" echo " t) Старт"
echo " p) Стоп" echo " p) Стоп"
echo " r) Перезапуск" echo " r) Перезапуск"
echo " d) Удалить" echo " e) Включить автозагрузку"
echo " d) Отключить автозагрузку"
echo " x) Удалить"
echo " l) Просмотр логов"
echo " b) Назад" echo " b) Назад"
ACTION_CHOICE=$(read_input "Действие: ") ACTION_CHOICE=$(read_input "Действие: ")
case "$ACTION_CHOICE" in case "$ACTION_CHOICE" in
s) ;; # Статус уже показан s) ;; # Статус уже показан
t) manage_tunnel "$TUNNEL_ID_MANAGE" "start";; t)
p) manage_tunnel "$TUNNEL_ID_MANAGE" "stop";; manage_tunnel "$TUNNEL_ID_MANAGE" "start"
r) manage_tunnel "$TUNNEL_ID_MANAGE" "restart";; 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) 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): ") CONFIRM_REMOVE=$(read_input "Вы уверены, что хотите удалить туннель $TUNNEL_ID_MANAGE? (y/N): ")
if [[ "$CONFIRM_REMOVE" =~ ^[Yy]$ ]]; then if [[ "$CONFIRM_REMOVE" =~ ^[Yy]$ ]]; then
manage_tunnel "$TUNNEL_ID_MANAGE" "remove" manage_tunnel "$TUNNEL_ID_MANAGE" "remove"
sleep 2
return # Возврат в меню туннелей после удаления return # Возврат в меню туннелей после удаления
fi 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;; b) break;;
*) log_message "Неизвестная опция." "$RED";; *) log_message "Неизвестная опция." "$RED";;
esac esac
@@ -909,14 +1320,31 @@ main_menu() {
while true; do while true; do
clear clear
echo -e "${BOLD}${CYAN}========================================================${NC}" echo -e "${BOLD}${CYAN}========================================================${NC}"
echo -e "${BOLD}${CYAN} SSH Tunnel Manager v1.0 (by Manus) ${NC}" echo -e "${BOLD}${CYAN} SSH Tunnel Manager v1.1 (by Manus) ${NC}"
echo -e "${BOLD}${CYAN}========================================================${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 if load_vps_settings; then
echo -e "${GREEN}✓ VPS настроен: $VPS_USER@$VPS_HOST:$VPS_PORT${NC}" echo -e "${GREEN}✓ VPS настроен: $VPS_USER@$VPS_HOST:$VPS_PORT${NC}"
else else
echo -e "${RED}✗ VPS не настроен. Начните с опции 1.${NC}" echo -e "${RED}✗ VPS не настроен. Начните с опции 1.${NC}"
fi 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 "" echo ""
list_tunnels list_tunnels
@@ -930,10 +1358,11 @@ main_menu() {
echo -e "6) ${BOLD}Настройка маршрутизации (iptables)${NC}" echo -e "6) ${BOLD}Настройка маршрутизации (iptables)${NC}"
echo -e "7) ${BOLD}Настройки SSH Демона (sshd)${NC}" echo -e "7) ${BOLD}Настройки SSH Демона (sshd)${NC}"
echo -e "8) ${BOLD}Показать публичный ключ${NC} (Для копирования на VPS)" echo -e "8) ${BOLD}Показать публичный ключ${NC} (Для копирования на VPS)"
echo -e "9) ${BOLD}Выход${NC}" echo -e "9) ${BOLD}Переустановка/обновление${NC}"
echo -e "0) ${BOLD}Выход${NC}"
echo "" echo ""
choice=$(read_input "Выберите опцию [1-9]: ") choice=$(read_input "Выберите опцию [0-9]: ")
case $choice in case $choice in
1) setup_vps ;; 1) setup_vps ;;
@@ -945,6 +1374,11 @@ main_menu() {
7) setup_ssh_config ;; 7) setup_ssh_config ;;
8) show_public_key ;; 8) show_public_key ;;
9) 9)
echo -e "${YELLOW}Выполняется переустановка...${NC}"
install_manager
read_input "Нажмите Enter для продолжения..."
;;
0)
log_message "Выход из менеджера." "$GREEN" log_message "Выход из менеджера." "$GREEN"
exit 0 exit 0
;; ;;
@@ -959,8 +1393,9 @@ main_menu() {
# --- Точка входа --- # --- Точка входа ---
# Главное изменение: если скрипт запущен без аргументов, выполняем автоматическую установку и запуск меню # Главное изменение: если скрипт запущен без аргументов, выполняем автоматическую установку и запуск меню
if [[ $# -eq 0 ]]; then if [[ $# -eq 0 ]]; then
echo -e "${BOLD}${CYAN}SSH Tunnel Manager v1.0${NC}" echo -e "${BOLD}${CYAN}SSH Tunnel Manager v1.1${NC}"
echo -e "Автоматический запуск установки и меню..." echo -e "Автоматический запуск установки и меню..."
echo ""
# Проверяем, установлен ли уже скрипт # Проверяем, установлен ли уже скрипт
if [ -f "/usr/local/bin/tunnel-manager" ]; then if [ -f "/usr/local/bin/tunnel-manager" ]; then
@@ -969,6 +1404,8 @@ if [[ $# -eq 0 ]]; then
main_menu main_menu
else else
echo -e "${GREEN}Начинаем установку...${NC}" echo -e "${GREEN}Начинаем установку...${NC}"
echo -e "${YELLOW}Установка займет несколько минут...${NC}"
sleep 2
install_manager install_manager
echo -e "${GREEN}Установка завершена. Запуск меню...${NC}" echo -e "${GREEN}Установка завершена. Запуск меню...${NC}"
sleep 2 sleep 2
@@ -983,7 +1420,7 @@ else
main_menu main_menu
;; ;;
*) *)
echo -e "${BOLD}${CYAN}SSH Tunnel Manager v1.0${NC}" echo -e "${BOLD}${CYAN}SSH Tunnel Manager v1.1${NC}"
echo -e "Использование:" echo -e "Использование:"
echo -e " 1. Запуск одной командой (автоустановка + меню):" 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 " curl -s https://git.softuniq.eu/OpenDoor/vps_ssh_tunel/raw/branch/main/install_ssh_tunnel.sh | sudo bash"