Files
knowledge-base/projects/dttb/rustdesk.md
dttb d58873368a RustDesk: pre-prod security audit + операционный runbook
Аудит перед запуском в прод. Найдены и исправлены critical и medium issues:

Critical (fixed):
- File permissions 644 → 600/640 для id_ed25519, БД, config.yaml
- Нет logrotate (диск 2GB зальётся) → /etc/logrotate.d/rustdesk
- Нет авто-бэкапа → daily cron 03:00 в /root/rustdesk-backups/

Medium (fixed):
- Brute-force на /api/admin/login → NPM rate-limit 5r/m

Medium (deferred):
- NC share без пароля (NC сейчас down — отдельный task)
- Security headers не наследуются в location / (NPM template limitation)

Документация:
- decisions/2026-04-30-rustdesk-pre-prod-audit.md — полный отчёт
- projects/dttb/rustdesk-runbook.md — операционный runbook (recovery,
  troubleshooting, onboarding, updates)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-30 10:42:19 +03:00

12 KiB
Raw Blame History

date, type, tags
date type tags
2026-04-28 project-reference
rustdesk
lxc116
lejianwen
dttb

RustDesk Server — справочник

Что это

Self-hosted Remote Desktop сервер для парка ~30-50 машин (НИИКН + клиенты). Стек lejianwen/rustdesk-server-pro 1.1.14 (hbbs/hbbr) + lejianwen/rustdesk-api 2.7 на нативной Debian-установке (без Docker), с MUST_LOGIN=Y.

История миграции: ../../decisions/2026-04-28-rustdesk-lejianwen-pro-migration

Где живёт

  • LXC 116 rustdeskserver на Proxmox 10.0.0.250
  • IP: 10.0.0.244 (LAN) / 100.70.191.161 (NetBird)
  • Debian 12, 1 vCPU / 512M / 2G — community-script установка

Домен

Сервисы (systemd)

rustdesk-hbbs.service   — ID/Rendezvous server (hbbs --must-login Y -k _ -r remot.dttb.ru:21117)
rustdesk-hbbr.service   — Relay server (hbbr -k _)
rustdesk-api.service    — Web admin + REST API (на 21114)

Бинари:

  • /usr/bin/hbbs — pro 1.1.14 (с патчем --must-login Y)
  • /usr/bin/hbbr — pro 1.1.14
  • /usr/bin/rustdesk-api — 2.7
  • /usr/bin/{hbbs,hbbr}.oss-1.1.14 — rollback-копии

apt-mark hold rustdesk-server-hbbs rustdesk-server-hbbr — apt не перезапишет.

Override-конфиги:

  • /etc/systemd/system/rustdesk-hbbs.service.d/override.conf
  • /etc/systemd/system/rustdesk-hbbr.service.d/override.conf

Порты

Порт Протокол Назначение
21114 TCP rustdesk-api HTTP (только через NPM HTTPS!)
21115 TCP hbbs NAT-test
21116 TCP+UDP hbbs ID/rendezvous (UDP — основной)
21117 TCP hbbr relay
21118 TCP hbbs WebSocket (для All-In-HTTPS клиентов через /ws/id)
21119 TCP hbbr WebSocket (через /ws/relay)

NPM Proxy Host id=14: https://remot.dttb.ru → 10.0.0.244:21114 + custom nginx с /ws/id и /ws/relay. NPM Streams: id 38-43 (21115/TCP, 21116/UDP, 21116/TCP, 21117/TCP, 21118/TCP, 21119/TCP) → 10.0.0.244.

Ключи

  • /var/lib/rustdesk-server/id_ed25519 — приватный (88 байт)
  • /var/lib/rustdesk-server/id_ed25519.pubR0lA4r77hAGw6YRL1qG3JioVqQ0Q0fJfzkwlAGqR6jU=

Не перегенерировать! Иначе все ~30-50 клиентов перестанут подключаться.

БД

  • /var/lib/rustdesk-server/db_v2.sqlite3 — БД hbbs (peers state)
  • /var/lib/rustdesk-api/data/rustdeskapi.db — БД api (users, groups, address_books, audit_logs)

Пока SQLite. План: MySQL когда дойдём до HA.

Конфиг api

/var/lib/rustdesk-api/conf/config.yaml — основные параметры:

  • lang: ru
  • app.register: false (регистрация выключена — юзеров создаёт админ)
  • app.show-swagger: 1
  • app.ban-threshold: 5
  • app.captcha-threshold: 3
  • rustdesk.id-server: remot.dttb.ru:21116
  • rustdesk.relay-server: remot.dttb.ru:21117
  • rustdesk.api-server: https://remot.dttb.ru
  • rustdesk.key: <id_ed25519.pub>
  • jwt.key: <см. credentials>
  • ldap.enable: false

Шаблон RustDesk2.toml для клиентов

/root/RustDesk2.toml на LXC 116:

rendezvous_server = "remot.dttb.ru:21116"
nat_type = 1
serial = 1

[options]
custom-rendezvous-server = "remot.dttb.ru"
relay-server = "remot.dttb.ru"
api-server = "https://remot.dttb.ru"
key = "R0lA4r77hAGw6YRL1qG3JioVqQ0Q0fJfzkwlAGqR6jU="
allow-websocket = "Y"
verification-method = "use-permanent-password"
approve-mode = "password"

CLI-команды (на LXC 116)

# Сменить пароль admin
cd /var/lib/rustdesk-api && /usr/bin/rustdesk-api reset-admin-pwd <new-pw>

# Сменить пароль обычного юзера
cd /var/lib/rustdesk-api && /usr/bin/rustdesk-api reset-pwd <username> <new-pw>

# Список peers через sqlite
sqlite3 /var/lib/rustdesk-api/data/rustdeskapi.db \
  "select id, last_online_ip, datetime(last_online_time,'unixepoch') from peers order by last_online_time desc limit 10;"

# Список юзеров
sqlite3 /var/lib/rustdesk-api/data/rustdeskapi.db \
  "select id, username, group_id, status, is_admin from users;"

# Логи
tail -f /var/log/rustdesk-server/hbbs.log
tail -f /var/log/rustdesk-server/hbbr.log
tail -f /var/log/rustdesk-api/rustdesk-api.log

Бэкап и rollback

  • /root/rustdesk-backup-20260428-1134/ — бэкап от 2026-04-28 миграции (ключи, БД, config.yaml.orig)
  • /root/rustdesk-rollback.sh — откат к OSS bin'ам за 30 сек

Operational runbook

Полный operational runbook (recovery, troubleshooting, onboarding нового клиента, обновления): rustdesk-runbook.

Pre-production audit (2026-04-30) с найденными уязвимостями + fixes: ../../decisions/2026-04-30-rustdesk-pre-prod-audit.

Применённые фиксы (2026-04-30):

  • File permissions: id_ed25519 644→600, БД и config.yaml 644→640
  • Logrotate /etc/logrotate.d/rustdesk (daily, 14 дней)
  • Auto-backup cron 03:00 → /root/rustdesk-backups/
  • NPM rate-limit на /api/admin/login (5r/m) и /api/login (10r/m)

Известные нюансы

  • MUST_LOGIN работает только в pro-бинаре hbbs. OSS hbbs (как был до 2026-04-28) этот флаг игнорирует. См. ../../decisions/2026-04-28-rustdesk-lejianwen-pro-migration.
  • Admin REST API через curl без web-сессии не пускает. Юзеров/группы создавать через https://remot.dttb.ru/_admin/.
  • Admin генерит /webclient2/-ссылки на peer'ы, а api отдаёт WebClient на /webclient/баг lejianwen 2.7. В NPM Proxy Host 14 (advanced_config) добавлен return 301 /webclient/$1$is_args$args для /webclient2/....
  • NPM streams API — PUT не работает (валидатор additional properties). Только DELETE + POST.
  • NPM streams через UI/API не публикуются наружу docker-контейнера. Нужно править compose-файл и пересоздавать контейнер. Compose лежит в /data/compose/2/docker-compose.yml на host LXC 103 (мы его положили туда, ранее Portainer хранил только в своём volume). При обновлении stack ВАЖНО: cd /data/compose/2 && docker compose -p npm up -d — relative ./data resolve в /data/compose/2/data (где реальные данные NPM). НЕ обновляй stack через Portainer UI — он работает со своей копией compose в /var/lib/docker/volumes/portainer_data/_data/compose/2/, может перезаписать. Текущий compose содержит ports: 80, 81, 443, 21115-21119 (TCP+UDP где надо).
  • WebClient в браузере работает на инфра-уровне (wss://remot.dttb.ru:21118/ws/id и :21119/ws/relay → 101 Switching Protocols). TLS termination для 21118/21119 через /data/compose/2/data/nginx/custom/stream.conf (custom stream block в NPM с listen 21118 ssl + ssl_certificate /etc/letsencrypt/live/npm-41/...). Streams 21115/21117/21116-tcp/udp идут через обычные NPM streams (id 38, 39, 40, 43). Чтобы реально использовать — нужны online peers с api-server login. Подключение Mac→Mac через WebClient невозможно (это и есть MUST_LOGIN-style ошибка "не удалось подключиться к серверу ретрансляции").
  • community-script может пытаться обновить пакетыapt-mark hold защищает hbbs/hbbr, но если запустить полный re-run скрипта community-scripts, могут быть сюрпризы. Не запускать без необходимости.
  • /proc/loadavg в LXC = нагрузка хоста, не контейнера (../../../knowledge-base/feedback_lxc_loadavg в memory).

Развёртывание клиентов

В Nextcloud в корне создан пакет RustDesk install/ с готовыми установщиками для всех платформ + автоматические скрипты. Подробности: ../../decisions/2026-04-29-rustdesk-client-deployment-package.

RustDesk install/                        ~766 MB
├── README.md                            инструкция для клиента
├── RustDesk2.toml                       шаблон конфига
├── windows/  (.exe + .msi + Install-Windows.ps1/.bat)
├── linux/    (deb x64+arm64, rpm x64+arm64, AppImage, install-linux.sh)
├── macos/    (.dmg aarch64+x86_64, install-macos.sh)
└── android/  (universal.apk)

Workflow для нового клиента:

  1. Олег делает public share-link в Nextcloud (с паролем — установщики содержат key)
  2. Клиент скачивает свою папку, запускает скрипт (двойной клик Install-Windows.bat или sudo bash install-linux.sh)
  3. Скрипт ставит RustDesk + кладёт RustDesk2.toml + генерит permanent password + выводит ID+pw
  4. Клиент шлёт ID+pw админу, админ привязывает peer к нужной группе через /_admin/

Версия: RustDesk 1.4.6 (релиз март 2026). Обновлять при выпуске новой версии — заменить файлы в папке + обновить 1.4.6 в README/скриптах.

Permanent password: auto-generated 10 символов per-machine, сохраняется в:

  • Windows: C:\Users\Public\rustdesk-credentials.txt
  • Linux: /root/rustdesk-credentials.txt (chmod 600)
  • macOS: ручная установка через UI (sandboxing)

Что НЕ делает скрипт:

  • Auto-login в API (требует service-token, отдельная задача) → клиент должен залогиниться сам через RustDesk UI Settings → Account, иначе MUST_LOGIN=Y отбивает входящие connections
  • Configure Android (вручную вводит настройки)

TODO

  • Раскатать RustDesk install/ пакет на парк (~30-50 машин)
  • Заполнить группы клиентских организаций в /_admin/
  • One-liner deployment script на сервере (https://remot.dttb.ru/install/win.ps1 etc.)
  • Configuration Strategy в lejianwen-api для push existing клиентам
  • rustdesk-utils 2.x для rustdesk-licensed-*.exe (single-file deploy)
  • Auto-login клиента в API через service-token (упростит post-install)
  • Бэкап БД API + ключей на ArtLeon через cron + rsync (NetBird)
  • Через 2-4 недели — миграция в Docker lejianwen/rustdesk-server-s6 (Вариант A3 из decision-файла)
  • MCP-обёртка поверх Swagger API для управления из Claude Code
  • HA-схема на втором экземпляре (НИИКН Proxmox) с общей MySQL