Apache Guacamole: Один портал для всех удаленных подключений

Apache Guacamole: установка и настройка SSH RDP VNC через браузер
Быстрый ответ: что такое Apache Guacamole и зачем он нужен
Apache Guacamole — это веб-шлюз удаленного доступа без клиентского ПО. Открываешь браузер, вводишь адрес, получаешь SSH, RDP или VNC к любому серверу в сети. Никаких плагинов, никаких отдельных клиентов. Все подключения в одном месте, снаружи виден только один порт твоего шлюза.

Apache Guacamole: установка, настройка и подключение SSH, RDP, VNC через браузер

Ты сейчас держишь в голове пять разных клиентов. PuTTY для SSH, mstsc для RDP, какой-нибудь TigerVNC для VNC, отдельный SSH-туннель для Kubernetes и ещё что-то для экзотики. Каждый раз когда подключаешься с нового устройства — ставишь всё заново. Каждый раз когда надо дать доступ коллеге — объясняешь по телефону как настроить клиент.

Guacamole закрывает эту боль. Один раз поднял шлюз — и больше не думаешь о клиентах.

В этой статье разберём: что внутри, как поднять через Docker Compose за 15 минут, как добавить подключения SSH/RDP/VNC, как это защитить и что делать когда сломается. Без воды.

Что нужно перед стартом

Компонент Минимум Рекомендовано
ОС Ubuntu 20.04 LTS Ubuntu 22.04 LTS / Debian 12
RAM 2 GB 4 GB
CPU 1 ядро 2 ядра
Диск 10 GB 20 GB
Docker 20.10+ 24.x+
Docker Compose v2.0+ v2.20+
Apache Guacamole 1.5.x 1.5.5 (актуальна на момент публикации)
PostgreSQL 13 15

Перед установкой проверь свежие релизы на hub.docker.com/r/guacamole/guacamole — версии обновляются.

Доступы которые нужны: root или sudo на сервере, открытый порт 8080 (или любой другой который выберешь для шлюза).

Архитектура: как это вообще работает

Прежде чем копировать команды — разберись с архитектурой. Иначе потом не поймёшь почему что-то не работает.

Guacamole состоит из двух частей:

guacd — демон на C. Это движок. Он принимает соединения от веб-приложения и транслирует их в нативные протоколы: RDP, SSH, VNC, Telnet. Никакой логики, никакого UI — только транспорт.

guacamole-client — Java-приложение в Tomcat. Это веб-интерфейс. Он аутентифицирует пользователей, хранит конфиги подключений в базе и общается с guacd по протоколу Guacamole.

Поток данных выглядит так:

%%{init: {
  'theme': 'base',
  'themeVariables': {
    'primaryColor': '#ffffff',
    'primaryTextColor': '#1e293b',
    'primaryBorderColor': '#94a3b8',
    'lineColor': '#64748b',
    'fontSize': '15px',
    'fontFamily': 'ui-sans-serif, system-ui, sans-serif'
  },
  'flowchart': {'curve': 'linear', 'nodeSpacing': 50, 'rankSpacing': 50}
}}%%
flowchart TD
    A["Браузер пользователя"] --> B["guacamole-client\nTomcat / Java\nport 8080"]
    B --> C["guacd\nDaemon / C\nport 4822"]
    C --> D["SSH\nport 22"]
    C --> E["RDP\nport 3389"]
    C --> F["VNC\nport 5900"]
    B --> G["PostgreSQL\nКонфиги и пользователи"]
    style A fill:#f8fafc,stroke:#3b82f6,stroke-width:2px,color:#1e40af
    style B fill:#f8fafc,stroke:#22c55e,stroke-width:2px,color:#15803d
    style C fill:#f8fafc,stroke:#f97316,stroke-width:2px,color:#9a3412
    style D fill:#f8fafc,stroke:#94a3b8,stroke-width:1px,color:#1e293b
    style E fill:#f8fafc,stroke:#94a3b8,stroke-width:1px,color:#1e293b
    style F fill:#f8fafc,stroke:#94a3b8,stroke-width:1px,color:#1e293b
    style G fill:#f8fafc,stroke:#94a3b8,stroke-width:1px,color:#1e293b

Ключевой момент: снаружи открыт только порт 8080 (или 443 после настройки Nginx). SSH, RDP и VNC порты целевых серверов наружу не торчат — к ним ходит guacd изнутри сети. Это и есть главный плюс с точки зрения безопасности.

Таблица портов

Сервис Порт Направление Описание
guacamole-client 8080/tcp входящий (от пользователей) Веб-интерфейс, перекрывается Nginx на 443
guacd 4822/tcp внутренний (client → guacd) Только между контейнерами, наружу не открывать
PostgreSQL 5432/tcp внутренний (client → db) Только между контейнерами
SSH цели 22/tcp исходящий (guacd → цель) guacd подключается к целевым серверам
RDP цели 3389/tcp исходящий (guacd → цель) guacd подключается к целевым Windows
VNC цели 5900/tcp исходящий (guacd → цель) guacd подключается к VNC-серверам

Установка Apache Guacamole через Docker Compose

Буду честен: есть два пути — собирать из исходников и Docker. Из исходников — это зависимости, libfreerdp, libssl, patching, и два часа жизни которые ты не вернёшь. Docker — это 15 минут и рабочий шлюз. Выбор очевиден.

Шаг 1: Создай структуру проекта


mkdir -p ~/guacamole/init && cd ~/guacamole

Шаг 2: Сгенерируй SQL-схему для PostgreSQL

Guacamole не создаёт таблицы сам при первом запуске. Нужно запустить образ с флагом генерации схемы и сохранить SQL-файл.


docker run --rm guacamole/guacamole:1.5.5 /opt/guacamole/bin/initdb.sh --postgresql > ~/guacamole/init/initdb.sql

Проверь что файл не пустой:


wc -l ~/guacamole/init/initdb.sql
# Должно быть несколько сотен строк

Шаг 3: Создай docker-compose.yml


version: '3.9'

services:
  guacd:
    image: guacamole/guacd:1.5.5
    container_name: guacd
    restart: unless-stopped
    networks:
      - guacamole_net

  postgres:
    image: postgres:15-alpine
    container_name: guacamole-postgres
    restart: unless-stopped
    environment:
      POSTGRES_DB: guacamole_db
      POSTGRES_USER: guacamole_user
      POSTGRES_PASSWORD: ВАШ_СЛОЖНЫЙ_ПАРОЛЬ
    volumes:
      - postgres_data:/var/lib/postgresql/data
      - ./init:/docker-entrypoint-initdb.d:ro
    networks:
      - guacamole_net

  guacamole:
    image: guacamole/guacamole:1.5.5
    container_name: guacamole-web
    restart: unless-stopped
    depends_on:
      - guacd
      - postgres
    ports:
      - "8080:8080"
    environment:
      GUACD_HOSTNAME: guacd
      GUACD_PORT: 4822
      POSTGRES_HOSTNAME: postgres
      POSTGRES_PORT: 5432
      POSTGRES_DATABASE: guacamole_db
      POSTGRES_USER: guacamole_user
      POSTGRES_PASSWORD: ВАШ_СЛОЖНЫЙ_ПАРОЛЬ
    volumes:
      - drive:/drive:rw
    networks:
      - guacamole_net

networks:
  guacamole_net:
    driver: bridge

volumes:
  postgres_data:
  drive:

Обрати внимание: папка ./init монтируется в /docker-entrypoint-initdb.d. PostgreSQL автоматически выполнит все .sql файлы из этой папки при первом старте. Вот зачем мы генерировали схему на шаге 2.

Шаг 4: Запусти


cd ~/guacamole
docker compose up -d

Шаг 5: Проверь что всё поднялось


docker compose ps

Результат должен быть такой:


NAME                  STATUS          PORTS
guacd                 Up              4822/tcp
guacamole-postgres    Up              5432/tcp
guacamole-web         Up              0.0.0.0:8080->8080/tcp

Если какой-то контейнер в состоянии Exited — смотри логи:


docker compose logs guacamole
docker compose logs postgres

Шаг 6: Первый вход и смена пароля

Открой в браузере: http://IP_СЕРВЕРА:8080/guacamole

Логин: guacadmin, пароль: guacadmin

Критично: смени пароль немедленно
guacadmin с паролем guacadmin — это первое что пробуют боты. Зайди в Settings — Users — guacadmin и смени пароль до того как сделаешь что-либо ещё.

Настройка подключений

SSH-подключение к Linux-серверу

Иди в Settings — Connections — New Connection.

Поле Значение
Name Любое понятное имя
Protocol SSH
Hostname IP или DNS имя сервера
Port 22
Username Пользователь на сервере
Password Пароль (или оставь пустым если используешь ключ)
Private Key Вставь содержимое ~/.ssh/id_rsa если используешь ключ

Если используешь ключ — поле Password оставь пустым, иначе Guacamole попробует пароль и ключ проигнорирует.

Сохрани. Теперь на главной странице появится иконка подключения. Кликай — откроется терминал прямо в браузере.

RDP-подключение к Windows

Поле Значение
Protocol RDP
Hostname IP Windows-машины
Port 3389
Username Пользователь (с доменом: DOMAIN\user)
Password Пароль
Security mode NLA — если сервер поддерживает; Any — если не уверен
Ignore server certificate Включи если самоподписанный сертификат

Вот тут важно: если подключаешься к Windows Server и видишь ошибку аутентификации — сначала проверь что на целевой машине включён Remote Desktop и пользователь добавлен в группу «Remote Desktop Users». Это не Guacamole виноват.

VNC-подключение

Поле Значение
Protocol VNC
Hostname IP машины с VNC-сервером
Port 5900 (или 5901, 5902 — зависит от дисплея)
Password VNC-пароль

Подключение к Pod в Kubernetes

Хитрый случай. Прямого коннектора к Kubernetes у Guacamole нет — но есть обходной путь через SSH с начальной командой.

Настрой SSH-подключение к бастион-хосту или ноде кластера где есть kubeconfig. В поле Initial command на вкладке Terminal вставь:


kubectl exec -it ИМЯ_ПОДА -n NAMESPACE -- /bin/bash

При подключении по этому соединению сразу попадёшь в оболочку пода. Удобно для дежурных сценариев когда надо быстро зайти без терминала.

Видео по теме

Ссылка на оригинал на YouTube

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

Если у тебя несколько однотипных серверов — Guacamole умеет группировать их с балансировкой нагрузки.

Иди в Settings — Connection Groups — New Group.

Параметр Значение Когда использовать
Type: ORGANIZATIONAL Просто папка для группировки Логическая структура без балансировки
Type: BALANCING Балансировка по загрузке Терминальные фермы, кластеры

При типе BALANCING Guacamole будет отправлять нового пользователя на наименее нагруженное соединение в группе. Для терминальных ферм или кластеров из нескольких идентичных серверов — удобно.

HTTPS через Nginx: без этого в продакшн не идём

Guacamole на порту 8080 без TLS — это не продакшн. Ставим Nginx как reverse proxy.

Установка Nginx и Certbot


apt update && apt install -y nginx certbot python3-certbot-nginx

Конфиг Nginx для Guacamole


server {
    listen 80;
    server_name guacamole.example.com;
    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl;
    server_name guacamole.example.com;

    ssl_certificate /etc/letsencrypt/live/guacamole.example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/guacamole.example.com/privkey.pem;

    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers HIGH:!aNULL:!MD5;

    location / {
        proxy_pass http://127.0.0.1:8080/guacamole/;
        proxy_buffering off;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_read_timeout 3600;
        proxy_send_timeout 3600;
    }
}

Обрати внимание на proxy_read_timeout 3600. Это критично для SSH/RDP сессий — без этого Nginx будет рвать долгие соединения через стандартные 60 секунд.

Получи сертификат


certbot --nginx -d guacamole.example.com

Перезапусти Nginx


nginx -t && systemctl reload nginx

Безопасность

Минимальный чеклист безопасности перед выходом в продакшн
Это не рекомендации — это минимум без которого шлюз не должен быть доступен из интернета. Проверь каждый пункт.

UFW: закрой всё лишнее


ufw default deny incoming
ufw default allow outgoing
ufw allow ssh
ufw allow 80/tcp
ufw allow 443/tcp
# Порт 8080 оставляем закрытым снаружи - к нему ходит только Nginx изнутри
ufw enable
ufw status

Fail2ban для Guacamole

Guacamole пишет неудачные попытки входа в лог Tomcat. Настроим fail2ban на этот лог.


apt install -y fail2ban

Создай файл /etc/fail2ban/filter.d/guacamole.conf:


[Definition]
failregex = o.a.g.r.auth.AuthenticationService - Authentication attempt from  for user .* failed
ignoreregex =

Создай /etc/fail2ban/jail.d/guacamole.conf:


[guacamole]
enabled  = true
port     = 80,443
filter   = guacamole
logpath  = /var/lib/docker/containers/*/*.log
maxretry = 5
bantime  = 3600
findtime = 600

systemctl restart fail2ban
fail2ban-client status guacamole

Отдельный пользователь для каждой группы людей

Не давай guacadmin всем. Создай отдельных пользователей в Settings — Users и назначь им права только на нужные подключения. Принцип минимальных привилегий работает и здесь.

Двухфакторная аутентификация

Guacamole поддерживает TOTP через расширение. Скачай guacamole-auth-totp-1.5.5.jar с официального сайта и положи в:


# Создай папку для расширений и смонтируй её в контейнер
mkdir -p ~/guacamole/extensions
# Скачай расширение
wget -O ~/guacamole/extensions/guacamole-auth-totp-1.5.5.jar \
  https://downloads.apache.org/guacamole/1.5.5/binary/guacamole-auth-totp-1.5.5.jar

Добавь в docker-compose.yml в секцию volumes контейнера guacamole:


- ./extensions:/etc/guacamole/extensions:ro

Перезапусти контейнер — при следующем входе пользователю предложат настроить TOTP.

Резервное копирование

Что бэкапить: базу PostgreSQL с конфигами подключений и пользователями, папку extensions если используешь расширения.

Бэкап базы


#!/bin/bash
BACKUP_DIR=/opt/backups/guacamole
DATE=$(date +%Y%m%d_%H%M%S)
mkdir -p $BACKUP_DIR

docker exec guacamole-postgres pg_dump \
  -U guacamole_user guacamole_db \
  > $BACKUP_DIR/guacamole_db_$DATE.sql

# Удаляй бэкапы старше 30 дней
find $BACKUP_DIR -name "*.sql" -mtime +30 -delete

echo "Backup done: $BACKUP_DIR/guacamole_db_$DATE.sql"

Добавь в cron:


crontab -e
# Добавь строку:
0 3 * * * /opt/scripts/backup_guacamole.sh >> /var/log/guacamole_backup.log 2>&1

Восстановление из бэкапа


# Останови контейнеры
docker compose down

# Пересоздай том базы (удалит текущие данные)
docker volume rm guacamole_postgres_data

# Запусти только postgres
docker compose up -d postgres

# Восстанови из дампа
cat /opt/backups/guacamole/guacamole_db_ДАТА.sql | \
  docker exec -i guacamole-postgres psql -U guacamole_user guacamole_db

# Запусти остальные сервисы
docker compose up -d

Обновление Guacamole

Обновляй через смену тега образа в docker-compose.yml.


# Сделай бэкап базы ПЕРЕД обновлением
/opt/scripts/backup_guacamole.sh

# Измени версию в docker-compose.yml
# guacamole/guacamole:1.5.5 -> guacamole/guacamole:НОВАЯ_ВЕРСИЯ
# guacamole/guacd:1.5.5 -> guacamole/guacd:НОВАЯ_ВЕРСИЯ

# Подтяни новые образы и перезапусти
docker compose pull
docker compose up -d
Проверь release notes перед обновлением
Иногда между мажорными версиями меняется схема базы. В таких случаях нужна миграция. Это описано в официальных release notes на guacamole.apache.org/releases. Не игнорируй их.

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


# Статус контейнеров
docker compose ps

# Логи в реальном времени
docker compose logs -f guacamole

# Доступность веб-интерфейса
curl -s -o /dev/null -w "%{http_code}" http://localhost:8080/guacamole/

# Должен вернуть 200 или 302

# Проверка что guacd слушает
docker exec guacd netstat -tlnp | grep 4822

# Проверка подключения к базе изнутри контейнера guacamole
docker exec guacamole-web env | grep POSTGRES

Troubleshooting

Белый экран или 404 после открытия браузера

Причина: приложение ещё не запустилось. Tomcat стартует медленно.
Решение: подожди 30-60 секунд и обнови страницу. Если не помогает — смотри логи:


docker compose logs guacamole | tail -50

Ошибка «Cannot connect to guacd»

Причина: контейнер guacd не запустился или guacamole обращается по неправильному адресу.
Решение:


# Проверь что guacd работает
docker compose ps guacd

# Проверь что переменная GUACD_HOSTNAME совпадает с именем сервиса в compose
docker exec guacamole-web env | grep GUACD
# Должно быть GUACD_HOSTNAME=guacd

# Проверь сетевую связность между контейнерами
docker exec guacamole-web ping -c 3 guacd

Ошибка инициализации PostgreSQL: «relation does not exist»

Причина: SQL-схема не была применена при первом старте. Это бывает если том postgres_data уже существовал до монтирования init-папки.
Решение:


# Останови всё
docker compose down

# Удали том с данными (данные потеряются - это свежая установка)
docker volume rm guacamole_postgres_data

# Убедись что initdb.sql лежит в ./init/
ls -la ~/guacamole/init/initdb.sql

# Запусти снова
docker compose up -d

RDP подключение зависает или отваливается через несколько минут

Причина: таймаут proxy_read_timeout в Nginx.
Решение: убедись что в конфиге Nginx стоит proxy_read_timeout 3600 и proxy_send_timeout 3600.

SSH работает, но нет поддержки UTF-8 / кириллица не отображается

Причина: не настроена кодировка в параметрах подключения.
Решение: в настройках SSH-соединения на вкладке Terminal укажи:
— Terminal type: xterm-256color
— Font name: monospace

Не работает буфер обмена между браузером и сессией

Это фича браузеров, не баг Guacamole. Нажми Ctrl+Alt+Shift внутри сессии — откроется боковая панель Guacamole с буфером обмена. Вставляй текст туда, и он появится в сессии.

Альтернативы Apache Guacamole

Решение Плюсы Минусы Когда выбрать
Apache Guacamole Open source, активная разработка, много протоколов Java в стеке, требует отдельного guacd Универсальный шлюз для смешанной среды
Teleport Встроенный аудит, certificate-based auth, Kubernetes Сложнее в настройке, бесплатно только Community Когда нужен детальный аудит и compliance
MeshCentral Бесплатно, агентский доступ, встроенный relay Нужен агент на целевых машинах Когда нужно управлять конечными устройствами
RustDesk Server Простота, P2P, открытый код В основном для десктопов, слабее для серверов Поддержка пользователей, не серверная инфра

Guacamole выигрывает когда нужен централизованный шлюз без агентов на целевых серверах и с поддержкой смешанного парка: Linux по SSH, Windows по RDP, виртуалки по VNC.

Профилактика: как не сломать снова

  • Поставь мониторинг на доступность http://localhost:8080/guacamole/ — например через Uptime Kuma или простой curl в cron
  • Настрой автообновление сертификата: certbot сам добавляет таймер в systemd, проверь systemctl list-timers | grep certbot
  • Не храни пароли к подключениям в открытом виде — используй отдельного пользователя с минимальными правами для каждого критичного подключения
  • Логируй сессии: Guacamole умеет записывать RDP и SSH сессии в файлы. Включи через параметр Recording path в настройках соединения

FAQ

Почему Guacamole не видит новое SSH-подключение сразу после создания?

Видит. Просто иногда нужно обновить страницу. Кэширование на стороне браузера. Если соединение не появляется и после обновления — проверь что пользователь имеет права на это подключение в Settings — Connections — Permission.

Как проверить что guacd реально подключается к целевому серверу?


# Смотри логи guacd во время попытки подключения
docker compose logs -f guacd

# В момент когда кликаешь на соединение в браузере - увидишь строки типа:
# guacd[1]: INFO: Connection ID is "..."
# guacd[1]: INFO: Creating new client for protocol "ssh"

Если в логах пусто в момент клика — проблема между guacamole-client и guacd, не между guacd и целью.

Что если нужно дать временный доступ подрядчику?

Создай отдельного пользователя, дай права только на нужные соединения, после окончания работ — удали пользователя. Не давай guacadmin никому. Это стандартная практика.

Как записывать RDP и SSH сессии для аудита?

В настройках подключения найди раздел Screen Recording (для RDP) или Typescript recording (для SSH). Укажи путь к директории. Для Docker это должна быть директория внутри контейнера с примонтированным томом:


Recording path: /record
Recording name: ${GUAC_DATE}_${GUAC_TIME}_${GUAC_USERNAME}

Добавь том в docker-compose.yml:


volumes:
  - /opt/guacamole/recordings:/record:rw

Итог

Поднял Guacamole — закрыл несколько задач одновременно: централизованный доступ, аудит сессий, минимальная поверхность атаки снаружи. Больше не нужно объяснять коллеге как настроить PuTTY. Больше не нужно открывать RDP наружу.

Архитектура простая: guacd транслирует протоколы, клиент на Tomcat отдаёт веб-интерфейс, PostgreSQL хранит конфиги. Всё это живёт в трёх Docker-контейнерах и занимает 15 минут на поднятие.

Не заработало - разберёмся
Если что-то пошло не так — пиши в комментарии с логами из docker compose logs. Конкретный вывод конкретной команды. «Не работает» без логов — это не диагноз.

Оставайтесь на связи

Рецепты от IT-боли. Без воды, без рекламы, без маркетинговой шелухи.

Подписаться на IT-Аптеку →

Мы ВКонтакте

IT-Аптека — советы, новости и помощь рядом.

Вступить в группу ВКонтакте →
Поделитесь:

Оставьте комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Прокрутить вверх