MAATRIX / Блог / RustDesk на сервере: частые ошибки и решения

RustDesk на сервере: частые ошибки и решения

MAATRIX

Если вы подняли свой RustDesk-сервер вместо публичного rustdesk.com, рано или поздно упрётесь в одну из типовых проблем: клиент видит ID, но не подключается, ключ шифрования «не совпадает», файлы не передаются, а после перезапуска контейнера все клиенты теряют доступ разом. Ниже — разбор конкретных ошибок self-hosted RustDesk (hbbs + hbbr) с командами для диагностики и рабочими исправлениями, без «переустановите и попробуйте снова».

Обсудить статью, задать вопрос или начать новую тему

Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.

Перейти в сообщество →

Архитектура: hbbs, hbbr и что вообще нужно поднять

RustDesk-сервер — это два отдельных процесса, а не один:

  • hbbs (ID/rendezvous server) — держит реестр ID клиентов, помогает им найти друг друга и договориться о прямом соединении (NAT hole punching).
  • hbbr (relay server) — ретранслятор трафика, когда прямое P2P-соединение не удалось (что в реальности случается часто — симметричный NAT, строгий корпоративный файрвол и т.д.).

Оба процесса нужны одновременно: без hbbr клиенты за NAT будут видеть друг друга в списке, но не смогут подключиться или подключение будет обрываться на передаче файлов. Часто встречающаяся ошибка новичков — поднять только hbbs, потому что «relay вроде не обязателен». Формально да, но на практике без него у части пользователей соединение просто не установится.

Оба сервиса ставятся из официального образа rustdesk/rustdesk-server (есть варианты amd64 и arm64) либо бинарниками с GitHub-релиза проекта. Дальше — вариант через Docker Compose, он проще в обслуживании и позволяет быстро откатиться, если что-то пошло не так.

Рабочий docker-compose для hbbs + hbbr

Минимальный конфиг, который реально держит продакшн-нагрузку небольшой команды:

version: "3"
services:
  hbbs:
    image: rustdesk/rustdesk-server:latest
    container_name: hbbs
    ports:
      - "21115:21115"
      - "21116:21116/tcp"
      - "21116:21116/udp"
      - "21118:21118"
    command: hbbs -r your.server.ip:21117
    volumes:
      - ./data:/root
    restart: unless-stopped
    depends_on:
      - hbbr

  hbbr:
    image: rustdesk/rustdesk-server:latest
    container_name: hbbr
    ports:
      - "21117:21117"
      - "21119:21119"
    command: hbbr
    volumes:
      - ./data:/root
    restart: unless-stopped

Ключевые моменты, которые часто упускают:

  • ./data:/root обязательно должен быть общим volume для hbbs и hbbr и должен переживать перезапуск контейнера — именно здесь лежит пара ключей id_ed25519 / id_ed25519.pub, которую клиенты используют для проверки подлинности сервера.
  • -r your.server.ip:21117 в команде hbbs — это адрес relay-сервера, который сервер сообщает клиентам. Подставьте сюда реальный публичный IP или домен, а не localhost и не внутренний Docker-адрес — иначе клиенты за пределами вашей сети не смогут получить relay.
  • Порт 21118/21119 нужен только если планируете web-клиент (браузерное подключение); для «чистых» десктопных клиентов можно их не пробрасывать.

Если сервер уже поднят на голом Ubuntu/Debian без Docker, стоит сначала свериться с базовой установкой — например Docker с нуля на Ubuntu 24.04 или профильная статья по Docker на Debian 12, если сервер на Debian.

Нужен сервер под эту задачу?

Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.

Арендовать сервер

«Connection Failed» и клиент не видит сервер

Самая частая жалоба: клиент вводит ID и IP, но получает Connection Failed или зависает на «Connecting...». Проверяйте по порядку.

1. Проброшены ли порты на самом сервере. Проверка изнутри VPS:

sudo ss -tulnp | grep -E '21115|21116|21117|21118|21119'

Если процессы hbbs/hbbr не слушают ожидаемые порты — смотрите логи контейнеров (docker logs hbbs, docker logs hbbr) на предмет ошибок биндинга, чаще всего это конфликт с уже занятым портом или неверный volume-путь.

2. Открыт ли firewall на сервере. Для UFW:

sudo ufw allow 21115/tcp
sudo ufw allow 21116/tcp
sudo ufw allow 21116/udp
sudo ufw allow 21117/tcp
sudo ufw allow 21118/tcp
sudo ufw allow 21119/tcp
sudo ufw status

UDP на 21116 — не опечатка и не «на всякий случай»: именно по UDP идёт hole punching для попытки прямого соединения. Если забыть открыть UDP, P2P просто не будет пытаться устанавливаться, хотя TCP-порты будут отвечать. Подробный разбор типовых промахов с UFW — в статье Файрвол UFW на сервере: частые ошибки и решения.

3. Firewall/Security Group у провайдера. Многие забывают, что помимо UFW внутри системы есть ещё сетевой firewall на уровне облака или гипервизора — правила там нужно продублировать отдельно, ufw их не заменяет.

4. Совпадает ли адрес relay-сервера. Если в клиенте вручную указан ID-сервер, но relay-сервер (Key server) прописан неверно или вообще не задан — соединение упадёт именно на этапе, где нужен hbbr.

Ключ (Key) не совпадает — откуда берётся ошибка

Ошибка вида «Public key mismatch» или запрос ключа при каждом новом подключении почти всегда означает одно: у сервера пересоздался ключевой файл. Это происходит, если:

  • volume /root не был примонтирован постоянно, и при пересоздании контейнера (docker compose up -d --force-recreate, обновление образа, пересборка) hbbs сгенерировал новую пару ключей;
  • вы вручную удалили id_ed25519* из директории данных;
  • сервер разворачивали заново «с нуля» вместо переноса существующего volume.

Проверить текущий публичный ключ можно так:

cat ./data/id_ed25519.pub

Это значение и нужно указывать в клиентах в поле «Key» (Settings → Network → Key) — оно должно быть одинаковым на всех устройствах. Если ключ поменялся, самый чистый путь — обновить его во всех клиентах, а не пытаться откатить сервер: старый приватный ключ без резервной копии не восстановить.

Совет на будущее: сразу после первого запуска сделайте резервную копию файлов ключей отдельно от сервера:

cp ./data/id_ed25519 ./data/id_ed25519.pub ~/rustdesk-key-backup/

Это тот файл, потеря которого означает, что придётся заново прописывать ключ на каждом клиенте вручную.

NAT, симметричный NAT и почему без relay всё «наполовину работает»

Если экран передаётся, но зависает при передаче файлов, звук пропадает, или соединение периодически рвётся — вероятная причина в том, что клиенты находятся за симметричным NAT (типично для мобильных сетей и части корпоративных провайдеров), и прямое P2P-соединение невозможно в принципе — трафик обязан идти через hbbr.

Что стоит проверить:

  • hbbr действительно запущен и доступен извне (telnet your.server.ip 21117 или nc -zv your.server.ip 21117);
  • в команде запуска hbbs указан правильный флаг -r с адресом именно того сервера, где крутится hbbr (в большинстве схем это один и тот же VPS, но если вы разносите hbbs и hbbr по разным машинам — легко ошибиться с адресом);
  • на сервере достаточно пропускной способности канала — relay-трафик идёт через сервер целиком, в отличие от P2P, поэтому при нескольких одновременных сессиях с передачей экрана в хорошем разрешении канал стоит закладывать с запасом. Точных цифр по потреблению трафика на сессию не привожу — это сильно зависит от разрешения, частоты кадров и качества картинки, у вас цифры будут свои.

Если сервер держит одновременно несколько активных relay-сессий и ловит просадки — обычно это вопрос не CPU, а именно исходящей полосы, стоит смотреть vnstat или iftop в момент нагрузки.

Домен, TLS и веб-клиент перед RustDesk

Сам протокол RustDesk уже шифрует трафик между клиентом и сервером собственными ключами, поэтому TLS не обязателен для «классического» desktop-клиента. А вот если вы включаете web-клиент (порты 21118/21119, подключение из браузера), стоит закрыть его доменом с валидным сертификатом — иначе браузер будет ругаться на смешанный контент или блокировать WebSocket-соединение по wss://.

Типичная схема — reverse proxy на nginx перед портом 21118:

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

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

    location / {
        proxy_pass http://127.0.0.1:21118;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header Host $host;
    }
}

Сертификат проще всего выпустить через certbot — если ранее не настраивали Let's Encrypt на этом сервере, пошагово это описано в статье Let's Encrypt SSL на VPS: установка и настройка. Домен для сервера должен указывать на IP машины заранее — если DNS ещё не настроен, начните с настройки домена и DNS с нуля (или профильной статьи под вашу ОС).

Важно: reverse proxy закрывает только web-клиент. Порты 21115-21117 для «обычных» desktop-клиентов nginx не трогает, они идут напрямую по TCP/UDP на сервер — прятать их за прокси не требуется и не имеет смысла, RustDesk использует их не как HTTP.

Нужен сервер под эту задачу?

Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.

Арендовать сервер

Нужны сами нейросети для контента?

Генерируйте изображения, видео и озвучку нейросетями на falapi.io — десятки моделей в одном окне. Оплата картой РФ и по СБП.

Частые вопросы

Можно ли запустить hbbs и hbbr на разных серверах?

Да, но тогда в команде hbbs флаг -r должен указывать на публичный адрес именно того сервера, где крутится hbbr, а на обеих машинах нужно открыть соответствующие порты. Для большинства сценариев проще держать оба процесса на одном VPS.

Нужен ли отдельный сервер под каждую команду/отдел?

Нет, один hbbs+hbbr спокойно обслуживает множество независимых пар клиентов — сервер работает только как посредник для установления соединения и relay, сами сессии между конкретными парами клиентов друг с другом не пересекаются.

Почему после обновления образа rustdesk-server клиенты попросили новый ключ?

Почти всегда потому, что volume с /root не был примонтирован постоянно и контейнер при пересоздании сгенерировал новую пару ключей. Решение — держать директорию данных на persistent volume и делать резервную копию id_ed25519* отдельно.

Обязательно ли открывать UDP-порт 21116?

Да, если хотите, чтобы у клиентов была возможность прямого P2P-соединения (оно быстрее и не грузит канал сервера). Без UDP всё будет работать только через relay по TCP, что тоже рабочий вариант, но менее эффективный при нескольких одновременных сессиях.

Как ограничить сервер, чтобы им не мог пользоваться кто попало?

Задать общий Key (проверка публичного ключа сервера) недостаточно для контроля доступа к самому серверу — это защита от подмены сервера, а не whitelisting пользователей. Для ограничения доступа к hbbs используйте firewall по IP-адресам (если у команды статические адреса) или разверните RustDesk Server Pro с админкой, если нужна полноценная модерация пользователей.

Обсудить статью, задать вопрос или начать новую тему

Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.

Перейти в сообщество →