Настройка собственного relay-сервера RustDesk на VPS
Руководство по запуску hbbs и hbbr на своем сервере. Узнайте, как правильно настроить Ed25519 ключи, зафиксировать версии образов и ограничить порты для безопасной работы.
Что такое self-hosted relay-сервер RustDesk
Self-hosted relay-сервер RustDesk — это два демона на одном VPS. hbbs — это сервер идентификации и установления соединения (rendezvous server): он регистрирует ID каждого клиента и связывает двух клиентов между собой. hbbr — это relay-сервер: он передает байты сессии, но только для тех соединений, которые не удалось установить напрямую. Большинство руководств предлагают установить оба компонента, настроить сопряжение и на этом остановиться. Далее описана оставшаяся часть работы: ключ, который является вашим средством контроля доступа, порты, обновление и пропускная способность.
Оба демона поставляются в одном образе, rustdesk/rustdesk-server, и в приведенной ниже настройке оба считывают одну и ту же пару ключей Ed25519 из одного и того же каталога. Это то, что вы настраиваете самостоятельно, а не значение по умолчанию: hbbs загружает или генерирует пару самостоятельно, но hbbr игнорирует ключи, если вы не запустите его с указанием одного из них. Ed25519 — это схема подписи с открытым ключом. Эта пара ключей определяет, с какими клиентами будет взаимодействовать ваш сервер, и за ней не стоит никакой базы данных пользователей.
hbbs и hbbr: какой демон расходует трафик
Трафик hbbs невелик и постоянен: регистрация ID и сигналы heartbeats, а также короткий обмен данными для установления связи между двумя узлами. Он работает постоянно и почти не потребляет ресурсов.
Трафик hbbr — это сама сессия. Кадры изображения передаются в одну сторону, сигналы клавиатуры и мыши — в другую, и каждый переданный байт сначала поступает на ваш VPS, а затем покидает его. Если провайдер учитывает только исходящий трафик, ретранслируемая сессия обходится вам в объем переданных данных. Если учитывается суммарный трафик, стоимость удваивается.
Ретрансляция — это резервный, а не основной путь. hbbs сначала пытается соединить два клиента напрямую, используя hole punching через NAT (network address translation), который находится перед каждым из них. Когда это удается, сессия не проходит через hbbr, и ваш лимит трафика остается нетронутым. Когда одна из сторон находится за NAT, который назначает новый порт для каждого направления, или за брандмауэром, блокирующим пробитый путь, сессия переключается на hbbr, и каждый кадр проходит через ваш VPS.
Одна переменная окружения лишает вас этого выбора. ALWAYS_USE_RELAY=Y в hbbs принудительно направляет все сессии через hbbr. Документация RustDesk приводит этот параметр в одном из примеров Compose, поэтому его часто копируют. Это делает соединения более предсказуемыми, но создает реальный расход исходящего трафика. Устанавливайте этот параметр осознанно, а не просто копируя настройки.
Какие порты требуются для self-hosted сервера RustDesk
Указанные ниже номера портов были проверены по документации сервера RustDesk и репозиторию rustdesk-server 10 октября 2026 года.
- TCP 21115, на hbbs: тест типа NAT.
- UDP 21116, на hbbs: регистрация ID и heartbeat. Это путь, который клиент использует по умолчанию.
- TCP 21116, на hbbs: регистрация ID для клиентов, настроенных только на TCP, а также TCP hole punching и сервис соединений.
- TCP 21117, на hbbr: ретранслятор (relay). Это порт, через который передаются данные сессии, поэтому именно он влияет на потребление трафика.
- TCP 21118 на hbbs и TCP 21119 на hbbr: WebSocket, используется браузерным клиентом. Оставьте оба закрытыми, если не используете его.
- TCP 21114 — это HTTP API сервер в RustDesk Server Pro. Версия с открытым исходным кодом не слушает этот порт.
Установка hbbs и hbbr с фиксацией тега образа
services:
hbbs:
container_name: hbbs
image: rustdesk/rustdesk-server:1.1.16
command: hbbs
volumes:
- ./data:/root
network_mode: "host"
depends_on:
- hbbr
restart: unless-stopped
hbbr:
container_name: hbbr
image: rustdesk/rustdesk-server:1.1.16
command: hbbr -k _
volumes:
- ./data:/root
network_mode: "host"
restart: unless-stoppedmkdir -p ~/rustdesk
cd ~/rustdesk
# save the block above as ~/rustdesk/compose.yml before this line
sudo docker compose up -d
sudo docker compose psОба сервиса должны считывать running. Убедитесь, что слушающие порты активны, прежде чем настраивать межсетевой экран.
sudo ss -tlnp | grep -E ':2111[5-7]'
sudo ss -ulnp | grep ':21116'Вы должны увидеть TCP-порты 21115, 21116 и 21117 в режиме прослушивания, а также UDP-порт 21116. Отсутствие строки UDP означает, что hbbs не запущен, так как hbbs открывает этот порт при старте, и именно по нему клиенты регистрируются по умолчанию.
Четыре параметра в этом файле выбраны намеренно. Тег имеет значение 1.1.16 — это актуальный релиз на октябрь 2026 года, опубликованный 20 июля 2026 года. Мы используем его вместо latest, так как latest означает любую версию, загруженную последней, и через полгода docker compose pull может предоставить вам сервер, который вы не тестировали. Параметр network_mode: "host" привязывает порты напрямую к интерфейсам хоста, что рекомендуется в документации RustDesk и определяет поведение вашего межсетевого экрана. Параметр ./data:/root проецирует рабочую директорию образа на хост, чтобы пара ключей сохранялась в месте, доступном для резервного копирования. Параметр hbbr -k _ — это единственное отличие от исходного примера, так как настройки по умолчанию оставляют ваш ретранслятор открытым для всех. Если вы новичок в Compose, в статье запуск Docker Compose на VPS описаны формат файла и команды управления жизненным циклом.
Если hbbr когда-либо будет перенесен на другой сервер, hbbs должен знать, куда именно: передайте флаг -r relay.example.com:21117 или установите переменную окружения RELAY-SERVERS. Если все компоненты находятся на одном узле, это не требуется.
Пара ключей Ed25519 как средство контроля доступа
При первом запуске hbbs генерирует id_ed25519 и id_ed25519.pub в своей рабочей директории. Благодаря указанному выше монтированию, оба файла появятся на хостовой машине.
ls -l ~/rustdesk/data/
sudo cat ~/rustdesk/data/id_ed25519.pubid_ed25519.pub содержит одну строку в формате base64. Эту строку необходимо вставить в поле Key на каждом клиенте. id_ed25519 — это закрытая часть ключа, которая никогда не должна покидать сервер. Открытый ключ не является секретным, так как он в любом случае копируется в конфигурацию каждого клиента. Закрытый ключ — это секрет: любой, кто им владеет, может развернуть сервер, которому будут доверять ваши клиенты.
Создайте резервную копию обоих файлов прямо сейчас, пока вы не настроили двадцать клиентов.
sudo tar czf ~/rustdesk-keys.tgz -C ~/rustdesk/data id_ed25519 id_ed25519.pub
sudo chmod 600 ~/rustdesk-keys.tgzСкопируйте этот архив с сервера. Вот почему это важнее любого другого шага. Если удалить ~/rustdesk/data или переустановить систему на новом VPS, не скопировав этот файл, hbbs при следующем запуске сгенерирует новую пару ключей. У всех клиентов останется старый открытый ключ, поэтому hbbs отклонит их подключения, и клиенты перейдут в офлайн. Выполните sudo cat ~/rustdesk/data/id_ed25519.pub и сравните результат с полем Key на любом клиенте: строки перестанут совпадать, и именно это несоответствие станет причиной сбоя. Исправление потребует ручного редактирования настроек на каждой машине, включая те, к которым вы подключались через RustDesk.
Ключ — это не пароль сессии, и их путаница приводит к тому, что пользователи пропускают один из этапов настройки. Ключ определяет, с какими клиентами будет взаимодействовать ваш сервер. Постоянный пароль или одноразовый код на управляемой машине определяет, кто может открыть сессию на этом устройстве. Вам нужны оба компонента, и наличие одного не компенсирует слабость другого.
Почему неавторизованный ретранслятор представляет проблему
По умолчанию hbbr не выполняет никаких проверок. В документации по настройке RustDesk это указано прямо: пустой ключ позволяет клиентам без соответствующего ключа использовать ретранслятор. Пустое значение по умолчанию существует для того, чтобы новые пользователи не сталкивались с ошибками несовпадения ключей при первом запуске. Цена этого — любой, кто обнаружит ваш адрес на TCP 21117, сможет пропускать свой сессионный трафик через ваш VPS, расходуя ваш лимит передачи данных и используя ваш IP-адрес.
command: hbbr -k _ решает эту проблему. Аргумент _ указывает hbbr загрузить пару ключей из рабочей директории или сгенерировать её, если она отсутствует. Поскольку оба контейнера монтируют один и тот же ./data, используется та же пара, что и в hbbs. Ничего не нужно копировать вручную, поэтому расхождения невозможны.
Общий том — это часть, в которой люди часто ошибаются. Если дать hbbr собственную директорию, он сгенерирует другую пару ключей. В результате hbbs и hbbr перестанут «понимать» друг друга, все сессии через ретранслятор будут завершаться ошибкой, а прямые сессии продолжат работать. Симптом сбивает с толку: RustDesk подключается к одним узлам, но не к другим, в зависимости от того, удалось ли выполнить hole punching. Один ls -l ~/rustdesk/data/, показывающий единственную пару id_ed25519, исключает такое несовпадение. Это не доказывает, что ретранслятор проверяет ключи, так как hbbr игнорирует эти файлы, если он не был запущен с непустым ключом, поэтому проверьте также запущенную команду:
ps -eo args | grep '[h]bbr'Она должна вывести hbbr -k _. «Голый» hbbr означает, что ретранслятор по-прежнему открыт, независимо от того, что находится в директории.
Настройка клиентов для работы с вашим сервером
На каждой машине откройте RustDesk, затем перейдите в Settings, далее в Network и выберите ID/Relay Server.
- ID Server: имя вашего хоста, например
rustdesk.example.com. Клиент использует порт 21116, если вы не укажете другой. - Relay Server: оставьте пустым, если hbbr запущен на том же хосте, что и hbbs.
- API Server: оставьте пустым. В версии с открытым исходным кодом этот сервер не предусмотрен.
- Key: base64-строка из
id_ed25519.pub. Вставьте её точно, без пробелов в конце.
После этого в главном окне должно появиться сообщение о готовности клиента. Если этого не произошло, а клиент использует настройки по умолчанию, наиболее вероятная причина — отсутствие доступа к порту UDP 21116 на хосте hbbs, так как именно туда клиент по умолчанию отправляет запросы на регистрацию и heartbeat. Однако статус «офлайн» сам по себе не является доказательством этой проблемы. Клиент с установленной опцией disable-udp в значении Y выполняет регистрацию через TCP 21116 и не использует UDP 21116, поэтому для такого клиента в первую очередь проверьте доступность TCP 21116.
Ограничение портов, чтобы ретранслятор не стал открытым сервисом
Поскольку контейнеры используют сетевой режим host, перед ними нет правил Docker NAT, поэтому правила ufw применяются ожидаемым образом.
sudo ufw allow 22/tcp
sudo ufw allow 21115:21117/tcp
sudo ufw allow 21116/udp
sudo ufw enable
sudo ufw status numberedДобавьте 21118:21119/tcp только в том случае, если вы используете браузерный клиент. Держите вторую SSH-сессию открытой во время включения ufw, чтобы ошибка в правиле SSH не заблокировала вам доступ к серверу. В Основы работы с межсетевым экраном ufw на VPS описаны политики по умолчанию и порядок применения правил.
Теперь о ловушке. Если вы переключитесь на публикацию портов через блок ports:, что часто встречается в примерах для RustDesk с одним контейнером, Docker создаст собственные правила DNAT. Пакеты будут достигать контейнера, минуя цепочку, в которой находятся ваши правила ufw. В этом случае запрет ufw на порт 21117 не сработает, и ретранслятор окажется открытым для интернета, несмотря на то, что ufw status утверждает обратное. В Публикация портов Docker в обход ufw объясняется порядок цепочек. Сетевой режим host полностью исключает эту проблему. Если вы всё же публикуете порт, привязывайте его к конкретному адресу, как в "127.0.0.1:21118:21118" за обратным прокси-сервером.
Ограничение по исходному адресу работает только в том случае, если у ваших клиентов статические адреса.
sudo ufw allow from 203.0.113.0/24 to any port 21115:21117 proto tcp
sudo ufw allow from 203.0.113.0/24 to any port 21116 proto udpНоутбуки в сетях отелей не имеют статических адресов, именно поэтому ключ на hbbr здесь выполняет гораздо больше реальной работы, чем межсетевой экран.
Обновление стека с сохранением ключа
Ключ находится в bind mount, а не внутри контейнера, поэтому обновление безопасно, если вы не трогаете ./data.
- Сначала создайте резервную копию каталога с данными:
sudo tar czf ~/rustdesk-data-backup.tgz -C ~/rustdesk data. - Ознакомьтесь с примечаниями к выпуску для нового тега на странице релизов rustdesk-server.
- Отредактируйте
compose.ymlи измените обе строкиimage:на новый тег. - Выполните
sudo docker compose pull, затемsudo docker compose up -d. - Выполните
sudo cat ~/rustdesk/data/id_ed25519.pubи убедитесь, что строка совпадает с той, которая уже сохранена у ваших клиентов.
Шаг 5 — это критически важная проверка, так как изменение ключа на сервере происходит незаметно, но моментально разрывает связь со всеми клиентами. Откат выполняется путем возврата старого тега и повторного запуска up -d. Это работает только при условии фиксации версии: при использовании latest команда docker compose pull перенесла имя на новый образ, поэтому старый образ больше не имеет тега.
Обычно ключ теряется не из-за docker compose down, так как эта команда не затрагивает bind mount. Потеря происходит при миграции на новый VPS, если копируется только compose.yml. Вместе с ним обязательно копируйте ./data.
Мониторинг исходящего трафика при наличии лимита передачи данных
hbbr — единственный компонент этого стека, который расходует лимит трафика. Согласно FAQ RustDesk, одно ретранслируемое соединение при разрешении экрана 1920x1080 потребляет от 30 КБ/с до 3 МБ/с, а обычная офисная работа — около 100 КБ/с. Это опубликованные показатели для одной сессии, а не замеры вашей конкретной установки. При расчете на 60 часов в месяц (по 2 часа в день) показатели выглядят следующим образом.
Данные, на которых построен график
[
{
"label": "Low end, 30 KB/s",
"gb_per_month": 6.5
},
{
"label": "Office work, 100 KB/s",
"gb_per_month": 21.6
},
{
"label": "High end, 3 MB/s",
"gb_per_month": 648
}
]При интенсивности офисной работы одна сессия потребляет около 21.6 ГБ в месяц, что незаметно для любого тарифного плана. При максимальных опубликованных значениях те же 60 часов потребляют 648 ГБ, а две одновременные сессии с такой интенсивностью исчерпают лимит в 1 ТБ в течение месяца. Нижний предел составляет 6.5 ГБ. Гигабайты здесь считаются как 1000 МБ, что является стандартным способом учета лимитов передачи данных.
docker stats не предоставит вам детализацию, так как контейнер, использующий host networking, разделяет пространство имен сети с хостом, поэтому его счетчики совпадают со счетчиками хоста. Работают два других инструмента. vnstat измеряет показатели всего сервера целиком:
sudo apt install -y vnstat
sudo systemctl enable --now vnstat
vnstat -m«Весь сервер» означает именно это: если на данном VPS работает что-то еще, передающее значительные объемы данных, например, один из self-hosted серверов для фото, загружающий библиотеки с телефонов каждую ночь, его исходящий трафик попадет в ту же ежемесячную статистику, что и трафик вашего реле. То же самое касается медиасервера, поскольку, например, Halcyon, превращающий библиотеку Jellyfin в видеомагазин в стиле 90-х, транслирует контент пользователям, и этот исходящий трафик расходует тот же лимит, что и ваше реле.
Счетчик nftables позволяет измерить трафик конкретно для реле:
sudo nft add table inet relaymeter
sudo nft add chain inet relaymeter out '{ type filter hook output priority 0 ; }'
sudo nft add rule inet relaymeter out tcp sport 21117 counter
sudo nft list table inet relaymeterЭто правило не содержит вердикта, поэтому оно подсчитывает пакеты и байты, не меняя правила доступа, и находится в собственной таблице, чтобы не мешать работе ufw. Оно не является постоянным: добавьте те же строки в /etc/nftables.conf, если хотите сохранить их после перезагрузки. Счетчик увеличивается только во время активной ретрансляции сессии. Если счетчик продолжает расти, когда ни одна из ваших машин не подключена, значит, кто-то другой обнаружил ваше реле — именно для предотвращения таких случаев существует hbbr -k _. Поскольку вы не будете просматривать nft list каждое утро, настройте cron-задачу, которая сравнивает количество байт с пороговым значением и отправляет push-уведомление при его превышении; для этого подойдет ваш собственный сервер ntfy.
В hbbr также есть лимиты скорости, которые можно уменьшить. SINGLE_BANDWIDTH по умолчанию составляет 128 Мбит/с на одно ретранслируемое соединение, а TOTAL_BANDWIDTH — 1024 Мбит/с для всех соединений в сумме. Установка SINGLE_BANDWIDTH=8 ограничит одну сессию значением около 1 МБ/с. Это ограничивает скорость, а не месячный объем, поэтому рассматривайте это как способ предотвратить перегрузку канала одной сессией, а не как инструмент контроля бюджета.
Когда ретранслятор вообще не нужен
Для личного использования честный ответ заключается в том, что вам, возможно, ничего из этого не нужно. Объедините обе машины в mesh VPN и подключайтесь напрямую по адресу в туннеле. В этом случае не нужны hbbs, hbbr, исходящий трафик через ретранслятор и контейнеры на VPS, которые нужно обновлять.
На машине, которой вы хотите управлять, разрешите прямой доступ по IP в настройках безопасности RustDesk. Поле порта по умолчанию имеет значение 21118. Перед попыткой подключения убедитесь, что порт прослушивается:
ss -tlnp | grep 21118Затем подключайтесь к VPN-адресу этого узла вместо использования ID. В FAQ RustDesk указано, что в этом режиме соединение не шифруется, поэтому используйте его только внутри туннеля и никогда — через открытый интернет. Именно туннель обеспечивает шифрование.
Выбор зависит от того, кому принадлежат машины. Собственные hbbs и hbbr подходят, если вы обслуживаете чужие машины или работаете с людьми, которые не будут устанавливать VPN-клиент, так как с их стороны для настройки нужны только ID и пароль. Mesh VPN с прямым доступом по IP подходит, если все машины принадлежат вам и на них можно установить ключ. В сравнении WireGuard и Tailscale описаны два основных способа построения такой сети, а в запуске удаленного рабочего стола на Linux VPS рассматривается другой случай, когда машина, к которой нужен доступ, сама является сервером.
FAQ
Все ли сессии RustDesk проходят через мой ретранслятор?
Нет. hbbs сначала пытается соединить двух клиентов напрямую, используя пробивку NAT (hole punching) перед каждым из них. Только в тех сессиях, где это не удается, происходит переключение на hbbr, и только они расходуют ваш трафик. Исключением является ALWAYS_USE_RELAY=Y в hbbs, которая принудительно направляет каждую сессию через hbbr, независимо от наличия прямого пути. Если эта переменная задана в вашем файле Compose, каждый байт каждой сессии будет учитываться в вашем счете за передачу данных.
Где хранится ключ сервера RustDesk и что делать, если я его потеряю?
При первом запуске hbbs генерирует id_ed25519 и id_ed25519.pub в своей рабочей директории. В официальном образе эта директория — /root, поэтому при использовании указанного выше монтирования тома файлы появляются в ./data на хосте. Создайте резервные копии обоих файлов вне сервера. Если они будут утеряны, hbbs сгенерирует новую пару при следующем запуске, и всем клиентам, у которых остался старый открытый ключ, будет отказано в доступе. Восстановление невозможно, кроме как вручную изменить поле Key на каждом клиенте.
Какие порты нужно открыть для self-hosted сервера RustDesk?
TCP 21115, 21116 и 21117, а также UDP 21116. hbbs использует 21115 для проверки типа NAT, а 21116 — для регистрации ID и передачи сигналов (heartbeat) по UDP, а также для регистрации и пробивки NAT по TCP. hbbr использует 21117 для ретрансляции. TCP 21118 и 21119 — это порты WebSocket для браузерного клиента, поэтому оставьте их закрытыми, если вы его не используете. TCP 21114 относится к Pro HTTP API серверу, и сборке с открытым исходным кодом он не требуется.
Могут ли посторонние использовать мой self-hosted ретранслятор RustDesk?
Да, если вы запускаете hbbr с конфигурацией по умолчанию. В документации RustDesk указано, что пустой ключ позволяет клиентам без соответствующего ключа использовать ретранслятор, поэтому любой, кто узнает ваше имя хоста и порт 21117, сможет пропускать трафик через ваш сервер. Запускайте hbbr с -k _, чтобы он загружал ту же пару ключей, которую использует hbbs из общего тома ./data. После этого только клиенты, настроенные с вашим открытым ключом, смогут использовать вас в качестве ретранслятора.