- Подмена hbbs/hbbr на pro-бинари из docker lejianwen/rustdesk-server-s6, apt-mark hold - Systemd overrides: hbbs --must-login Y -k _ -r remot.dttb.ru:21117; hbbr -k _ - config.yaml: lang ru, домен remot.dttb.ru, ключ + jwt прописаны, swagger on - NPM Proxy Host 14: forward 10.0.0.244, SSL force, http2, /ws/id /ws/relay locations - NPM streams 21115-21119 пересозданы (id 38-43), Stream 30 удалён - Admin pw сменён, бэкап + rollback-скрипт в /root/rustdesk-* на LXC 116 - Ключ id_ed25519 идентичен до/после, 13 peers продолжают работать Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
10 KiB
10 KiB
date, type, tags
| date | type | tags | ||||||
|---|---|---|---|---|---|---|---|---|
| 2026-04-28 | migration |
|
RustDesk migration: OSS hbbs/hbbr → lejianwen-pro
Цель
Закрыть дыру: техник Клиента-А не должен подключаться к машинам Клиента-Б, даже зная ID и пароль. Это задача MUST_LOGIN=Y на уровне hbbs.
Что было
- LXC 116
rustdeskserver— Debian 12, 10.0.0.244 / 100.70.191.161 (NetBird) - Установлено через ProxmoxVE community-script (нативно, не Docker):
hbbs1.1.14 — OSS Purslane (поддерживает только--key,-r,--rendezvous-servers,ALWAYS_USE_RELAY)hbbr1.1.14 — OSSrustdesk-api2.7 — lejianwen (это уже не OSS, но без настроек: lang=zh-CN, jwt пустой, домен 192.168.1.66 мусорный)
- Конфиг
/var/lib/rustdesk-api/conf/config.yaml— почти дефолтный, никто не правил - БД
rustdeskapi.db352K с 1 admin user + 13 peers (внутренние LAN) - NPM Proxy Host 14 для
remot.dttb.ruсмотрел на мёртвый 10.0.0.43:21114, streams 30-35 на мёртвый 10.0.0.44, SSL force/HTTP/2/block_exploits всё off https://remot.dttb.ru/_admin/снаружи: 502 Bad Gateway (никто никогда не пользовался web-админкой через домен)- Peers всё равно работали: внутренние через LAN 10.0.0.244, внешние видимо через NetBird mesh / DNAT на роутере минуя NPM
Найденная развилка
OSS hbbs не понимает MUST_LOGIN. Этот патч есть только в lejianwen/rustdesk-server-pro (тот же бинарь, что в docker-образе lejianwen/rustdesk-server-s6). Без него изоляция работает только на уровне rustdesk-api (адресные книги по группам), но любой клиент с правильным ключом всё равно может ходить по ID минуя API.
Варианты
| Вариант | Действие | Плюс | Минус |
|---|---|---|---|
| A1 | Подменить только бинари hbbs/hbbr на pro, остальное оставить | Минимум потрясений, ключ/БД/api/NPM streams не трогаем | На LXC два разных способа управления (apt + override). apt-mark hold нужен |
| A2 | Оставить OSS, изоляция только через api | Ноль рисков ломки | Главное требование (изоляция по ID) не закрыто |
| A3 | Полная миграция в Docker s6 (как в исходном промте Олега) | Единый стек, проще будущие upgrades | Требует Docker, расширения rootfs LXC, миграции БД, больше точек отказа сейчас |
Выбран: A1. A3 — отдельной задачей через 2-4 недели когда дойдём до MySQL/HA/MCP-обёртки.
Что сделано
LXC 116
- Бэкап
/root/rustdesk-backup-20260428-1134/(ключи, db_v2.sqlite3, rustdeskapi.db, config.yaml.orig, systemd units, JWT, admin pw) - Pro-бинари извлечены из
lejianwen/rustdesk-server-s6:latestчерез docker на Proxmox-host (на самом 10.0.0.250 docker есть, в LXC 116 — нет):docker create --name rd-extract lejianwen/rustdesk-server-s6:latest docker cp rd-extract:/usr/bin/hbbs /tmp/... docker cp rd-extract:/usr/bin/hbbr /tmp/... pct push 116 ... - Подмена через
mv:/usr/bin/hbbs.oss-1.1.14← старый/usr/bin/hbbs← новый pro (поддерживает--must-login Y)
apt-mark hold rustdesk-server-hbbs rustdesk-server-hbbr— apt не перезапишет- Systemd overrides:
/etc/systemd/system/rustdesk-hbbs.service.d/override.conf:ExecStart= ExecStart=/usr/bin/hbbs -k _ -r remot.dttb.ru:21117 --must-login Y/etc/systemd/system/rustdesk-hbbr.service.d/override.conf:ExecStart= ExecStart=/usr/bin/hbbr -k _
config.yamlправки (точечно, без пересборки):lang: ruadmin.title: "Remote Support Portal"app.show-swagger: 1,ban-threshold: 5rustdesk.id-server / relay-server: remot.dttb.rurustdesk.api-server: https://remot.dttb.rurustdesk.key: R0lA4r77hAGw6YRL1qG3JioVqQ0Q0fJfzkwlAGqR6jU=(значениеid_ed25519.pub)rustdesk.key-file: /var/lib/rustdesk-server/id_ed25519.pubjwt.key: <openssl rand -base64 48>
- Admin pw сменён через CLI:
rustdesk-api reset-admin-pwd <pw>(cd в/var/lib/rustdesk-api/)
NPM (LXC 103 через API)
- Proxy Host 14 (id 14):
forward_host: 10.0.0.244,ssl_forced/http2/block_exploits=true,caching_enabled=false,allow_websocket_upgrade=true - Custom Nginx Configuration (advanced_config) добавлен с
location /ws/id(→21118) и/ws/relay(→21119) — для будущей All-in-HTTPS архитектуры (клиенты за корпоративными firewall'ами через 443) - Stream 30 (TCP 21114) удалён — API не должен жить голым TCP
- Streams 31-35 пересозданы (id 38-43) на 10.0.0.244 (PUT не работает на streams API —
additional propertiesошибка; делать DELETE+POST с минимальным body безcertificate_id) - Добавлен Stream id 43: 21116/TCP (id-server) дополнительно к Stream id 39: 21116/UDP
Подтверждения
sha256sum id_ed25519.pubидентичен до/после миграции (abfbebe9…a38c6b) ✅sha256sum id_ed25519(приватный) идентичен ✅MUST_LOGIN=Yявно в/var/log/rustdesk-server/hbbs.logпосле рестартаKey: R0lA4r77hAGw6YRL1qG3JioVqQ0Q0fJfzkwlAGqR6jU=тот жеPrivate key comes from id_ed25519— pro-hbbs нашёл существующий ключ, не перегенерировал- Все 7 портов 21114-21119 слушают
https://remot.dttb.ru/_admin/снаружи: HTTP/2 200 OK (раньше 502)- 13 существующих peers продолжают подключаться (БД та же)
Грабли
- community-script ставит OSS hbbs, не pro. Бинарь от Purslane Ltd. Версия 1.1.14 у обоих идентична, но pro имеет дополнительный CLI-флаг
--must-login Yи читаетMUST_LOGINenv. Проверка черезgrep -ao MUST_LOGIN /usr/bin/hbbs(stringsв LXC нет). - Admin API не пускает через curl даже с правильным admin-токеном из
/api/admin/login— требует web-сессию. Юзеров и группы создавать через UI. - NPM PUT на streams возвращает 400
additional properties— даже если отправить только разрешённые поля. Решение: DELETE + POST с минимальным body (5 полей: incoming_port, forwarding_host, forwarding_port, tcp_forwarding, udp_forwarding). Безcertificate_id. ENCRYPTED_ONLYenv-переменная не нашлась как строка в pro-бинаре hbbs. Возможно управляется через config или этого патча нет в публичномlejianwen/rustdesk-server-s6. MUST_LOGIN сам по себе закрывает изоляцию — шифрование RustDesk и так включено для key-серверов.- NPM streams для портов 21115-21119 по факту не использовались — peers подключались внутри LAN (10.0.0.244 напрямую) или через NetBird (100.70.191.161). Поэтому "поломанная" конфигурация NPM не мешала. Внешний DNAT на роутере dttb.ru вероятно идёт прямо на rustdesk-сервер минуя NPM (надо ещё разок проверить — или подтвердить что внешние клиенты ходят через NetBird).
Rollback
bash /root/rustdesk-rollback.sh — за 30 секунд:
- mv бинари обратно (
/usr/bin/hbbs.oss-1.1.14→/usr/bin/hbbs) - удаляет systemd overrides
- восстанавливает
config.yaml.orig - снимает apt-mark hold
- рестартует сервисы
NPM-настройки скриптом не откатываются — ручной откат через UI или из /data/database.sqlite LXC 103.
TODO (отдельные задачи)
- Создать клиентские группы и юзеров через web (Олег, в /_admin/)
- Протестировать изоляцию на тестовой клиентской машине
- Раскатать новый
RustDesk2.tomlна ~30-50 машин через GPO/скрипт (старые конфиги тоже работают — ключ тот же) - Бэкап БД API + ключей по cron на ArtLeon через NetBird/rsync
- Через 2-4 недели — миграция в Docker rustdesk-server-s6 (Вариант A3), MySQL/HA, MCP-обёртка
Связанные файлы
На LXC 116:
/root/rustdesk-backup-20260428-1134/— бэкап и креды/root/rustdesk-rollback.sh— откат (chmod 700)/root/RustDesk2.toml— шаблон клиента/root/rustdesk-migration-report.md— расширенный отчёт
В kb:
- projects/dttb/rustdesk — справочник по серверу
- projects/dttb/credentials — креды (admin pw, JWT_KEY)
- projects/dttb/proxmox-inventory — LXC 116 запись обновлена