Files
knowledge-base/projects/dttb/rustdesk-runbook.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

16 KiB
Raw Permalink Blame History

date, type, tags
date type tags
2026-04-30 runbook
rustdesk
runbook
operations
recovery
troubleshooting

RustDesk Server — Operational Runbook

Операционная инструкция для повседневной эксплуатации, troubleshooting и recovery.

Связанные документы:


1. Архитектура и компоненты

┌────────────────────┐
│  Public Internet   │
│  (через роутер     │
│   dttb.ru NAT)     │
└─────────┬──────────┘
          │ 443 (HTTPS)  21115-21119 (TCP/UDP)
          ▼
┌────────────────────────────────────┐
│  NPM (LXC 103, 10.0.0.195)         │
│  • TLS termination + reverse proxy │
│  • Custom stream.conf для wss      │
│  • Rate-limit на /api/login        │
└─────────┬──────────────────────────┘
          │ HTTP/plain TCP
          ▼
┌──────────────────────────────────────────┐
│  RustDesk Server (LXC 116, 10.0.0.244)   │
│  • hbbs (id-server, 21116/UDP+TCP)       │
│  • hbbr (relay, 21117 TCP)               │
│  • hbbs WebSocket :21118                 │
│  • hbbr WebSocket :21119                 │
│  • rustdesk-api 2.7 :21114 (web admin)   │
│  • SQLite DB                             │
│  └─ MUST_LOGIN=Y enforced                │
└──────────────────────────────────────────┘
Компонент Откуда Версия Where
hbbs lejianwen-pro (extracted from docker rustdesk-server-s6) 1.1.14 /usr/bin/hbbs
hbbr lejianwen-pro 1.1.14 /usr/bin/hbbr
rustdesk-api lejianwen rustdesk-api deb (community-script) 2.7 /usr/bin/rustdesk-api
nginx NPM (jc21/nginx-proxy-manager) 2.12.2 / OpenResty docker container npm-app-1
Cert Let's Encrypt renew auto /etc/letsencrypt/live/npm-41/
Bind systemd rustdesk-{hbbs,hbbr,api}.service LXC 116

2. Daily operations

2.1 Проверить здоровье сервера

# С Mac (или другой машины)
curl -ksI https://remot.dttb.ru/_admin/      # → 200 OK
curl -ksI https://remot.dttb.ru/webclient/   # → 200 OK

# WebSocket endpoints
curl -ks --http1.1 -H "Upgrade: websocket" -H "Connection: Upgrade" \
  -H "Sec-WebSocket-Version: 13" -H "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==" \
  --max-time 3 https://remot.dttb.ru:21118/ws/id 2>&1 | grep "101"

# Сервисы на LXC 116
sshpass -p '1qaz!QAZ' ssh root@10.0.0.250 \
  "pct exec 116 -- systemctl is-active rustdesk-hbbs rustdesk-hbbr rustdesk-api"

2.2 Кто сейчас в системе (peers онлайн)

# Login в админку
ADMIN_PWD=$(cat /root/rustdesk-backup-20260428-1134/admin-password.txt)  # на LXC 116
# или из kb: 1qaz!QAZ

# Веб-админка
open https://remot.dttb.ru/_admin/
# admin / 1qaz!QAZ → Devices/Peers вкладка

# Через SQL
sshpass -p '1qaz!QAZ' ssh root@10.0.0.250 "pct exec 116 -- sqlite3 \
  /var/lib/rustdesk-api/data/rustdeskapi.db \
  'select id, hostname, last_online_ip, datetime(last_online_time,\"unixepoch\") \
   from peers order by last_online_time desc limit 20;'"

2.3 Включить/выключить пользователя

В /_admin/ → Users → редактирование status (1=enabled, 2=disabled).

CLI смена пароля:

sshpass -p '1qaz!QAZ' ssh root@10.0.0.250 \
  "pct exec 116 -- bash -c 'cd /var/lib/rustdesk-api && /usr/bin/rustdesk-api reset-pwd <username> <new-pw>'"

3. Onboarding нового клиента

3.1 Workflow на стороне сервера

  1. Создать юзера в /_admin/ для клиентской организации (или техника):
    • admin → Users → "Add"
    • Username, password, group
  2. Создать группу (если нужна):
    • Groups → "Add"
    • Привязать к ней этого юзера
  3. Сообщить клиенту username/password + ссылку на установщик

3.2 Workflow на стороне клиента

  1. Скачать пакет из Nextcloud (см. [[../../decisions/2026-04-29-rustdesk-client-deployment-package]]):
    • Public link: см. в kb или генерится через NC API/UI
    • Файл: RustDesk-Setup-<OS>.zip (Windows ~23 MB, Linux ~190 MB, macOS ~57 MB)
  2. Распаковать, запустить:
    • Windows: Install-Windows.bat (UAC → Да)
    • Linux: sudo bash install-linux.sh
    • macOS: bash install-macos.sh
  3. После установки клиент получает ID + permanent password (показывается в конце скрипта + сохраняется в файл)
  4. Клиент шлёт ID/password админу
  5. Клиент логинится в RustDesk-приложении (Settings → Account → Sign in <его-username> / <password>)
    • Без login: MUST_LOGIN=Y отбрасывает входящие connections — peer виден как online но connect к нему отказан
  6. Админ в /_admin/ → Devices → находит peer ID → привязывает к нужной группе
# Через Nextcloud OCS API
APP_PWD=$(cat ~/.config/nextcloud-kb/app-password)
EXPIRY=$(date -v+30d +%Y-%m-%d 2>/dev/null || date -d "+30 days" +%Y-%m-%d)
SHARE_PWD="rustdesk-$(openssl rand -hex 4)"

curl -s -u "admin:$APP_PWD" -X POST \
  -H "OCS-APIRequest: true" \
  --data-urlencode "path=/RustDesk install/RustDesk-Setup-Windows.zip" \
  --data-urlencode "shareType=3" \
  --data-urlencode "permissions=1" \
  --data-urlencode "password=$SHARE_PWD" \
  --data-urlencode "expireDate=$EXPIRY" \
  "https://dttb.ru/ocs/v2.php/apps/files_sharing/api/v1/shares?format=json" | python3 -m json.tool

Ссылка публичная, с паролем + 30 дней expiration. Установщик содержит наш key=R0lA..., чтобы не утечь.

4. Troubleshooting

4.1 Сервер недоступен снаружи

Симптом: https://remot.dttb.ru/_admin/ не отвечает

# 1. NPM container жив?
sshpass -p '1qaz!QAZ' ssh root@10.0.0.250 \
  "pct exec 103 -- docker ps | grep npm"

# 2. Backend сервисы на LXC 116
sshpass -p '1qaz!QAZ' ssh root@10.0.0.250 \
  "pct exec 116 -- systemctl status rustdesk-hbbs rustdesk-hbbr rustdesk-api --no-pager"

# 3. Логи NPM
sshpass -p '1qaz!QAZ' ssh root@10.0.0.250 \
  "pct exec 103 -- docker exec npm-app-1 tail -30 /data/logs/proxy-host-14_error.log"

# 4. Логи rustdesk
sshpass -p '1qaz!QAZ' ssh root@10.0.0.250 \
  "pct exec 116 -- tail -30 /var/log/rustdesk-server/hbbs.log /var/log/rustdesk-api/rustdesk-api.log"

4.2 Peer показан online, но connect не работает

Чек-лист:

  1. Залогинен ли peer в API?

    sshpass -p '1qaz!QAZ' ssh root@10.0.0.250 "pct exec 116 -- sqlite3 \
      /var/lib/rustdesk-api/data/rustdeskapi.db \
      \"select * from user_tokens where device_id='<peer-id>';\""
    

    Если пусто → клиент не логинился через RustDesk Settings → Account → Sign in. MUST_LOGIN=Y отбивает.

  2. Heartbeat актуальный? В /_admin/ → Peers → "Last seen" должен быть < 5 минут.

  3. Релай работает? На клиенте RustDesk:

    • Settings → Network → ID server: remot.dttb.ru:21116
    • Settings → Network → Relay server: remot.dttb.ru:21117
    • Если поля пустые — RustDesk2.toml не подхватился (см. путь в section 5).

4.3 WebClient timeout / "Не удалось подключиться"

WebClient (/webclient/) Flutter имеет ограничения:

  • Mac→Mac не работает (controller не может быть peer'ом)
  • Peer offline → relay timeout → ошибка
  • Peer не залогинен → MUST_LOGIN отбивает

Используй desktop-клиент для рутинной работы. WebClient — emergency only.

4.4 Rate-limit заблокировал

Если 5 неудачных login → 503 Service Unavailable от NPM на 1 минуту. Подожди или login с другого IP.

После 5 неудачных также ban-threshold: 5 в lejianwen забанит на ~1 час по user-account (отдельно от NPM IP-ban).

5. Конфиги и пути

LXC 116

Что Путь Перм
id_ed25519 (приватный) /var/lib/rustdesk-server/id_ed25519 600
id_ed25519.pub /var/lib/rustdesk-server/id_ed25519.pub 600
db_v2.sqlite3 (hbbs) /var/lib/rustdesk-server/db_v2.sqlite3 640
rustdeskapi.db (api) /var/lib/rustdesk-api/data/rustdeskapi.db 640
api config /var/lib/rustdesk-api/conf/config.yaml 640
systemd hbbs override /etc/systemd/system/rustdesk-hbbs.service.d/override.conf
systemd hbbr override /etc/systemd/system/rustdesk-hbbr.service.d/override.conf
logs /var/log/rustdesk-server/, /var/log/rustdesk-api/
Бэкап (вручную) /root/rustdesk-backup-20260428-1134/ drwx—
Бэкап (auto, daily 03:00) /root/rustdesk-backups/ drwxr-xr-x
Auto-backup script /usr/local/bin/rustdesk-backup.sh 700
Cron /etc/cron.d/rustdesk-backup
Logrotate /etc/logrotate.d/rustdesk
Rollback script /root/rustdesk-rollback.sh 700

LXC 103 (NPM)

Что Путь
Compose файл /data/compose/2/docker-compose.yml (host) — содержит ports 21115-21119
Volume mount: NPM data /data/compose/2/data
Volume mount: LE /data/compose/2/letsencrypt
Custom http config /data/compose/2/data/nginx/custom/http.conf (limit_req_zone)
Custom stream config /data/compose/2/data/nginx/custom/stream.conf (TLS terminate 21118/21119)
Custom server_proxy /data/compose/2/data/nginx/custom/server_proxy.conf (security headers)
Proxy host 14 /data/compose/2/data/nginx/proxy_host/14.conf (auto-gen NPM)
Logs /data/compose/2/data/logs/proxy-host-14_*.log

6. Backup & Restore

6.1 Auto-backup

Cron на LXC 116 запускает /usr/local/bin/rustdesk-backup.sh ежедневно в 03:00.

  • Tarball в /root/rustdesk-backups/rustdesk-YYYYMMDD.tar.gz
  • Содержит: ключи + обе БД + config.yaml + systemd overrides
  • Retention: 30 дней (find -mtime +30 -delete)

6.2 Восстановление БД из backup

# Например, восстановить состояние на 5 дней назад
TARBALL=$(ls -1t /root/rustdesk-backups/rustdesk-*.tar.gz | head -5 | tail -1)

# Стоп
systemctl stop rustdesk-api rustdesk-hbbs rustdesk-hbbr

# Распаковка (поверх)
tar xzf "$TARBALL" -C /

# Старт
systemctl start rustdesk-hbbs rustdesk-hbbr rustdesk-api

6.3 Полный rollback к OSS

bash /root/rustdesk-rollback.sh — за 30 секунд откатит к pre-migration (OSS hbbs/hbbr).

7. Updates & Maintenance

7.1 Обновление RustDesk-сервера

Клиенты RustDesk-приложения автоматически обновляются с github releases (если включено auto-update). Сервер hbbs/hbbr не требует обновлений каждый месяц — обновлять при выпуске major версии (1.2.x → 1.3.x) или при security advisory.

# 1. Скачать новые pro-бинари из docker
docker pull lejianwen/rustdesk-server-s6:latest
docker create --name rd-extract lejianwen/rustdesk-server-s6:latest
docker cp rd-extract:/usr/bin/hbbs /tmp/hbbs.new
docker cp rd-extract:/usr/bin/hbbr /tmp/hbbr.new
docker rm rd-extract

# 2. Передать в LXC 116
pct push 116 /tmp/hbbs.new /usr/bin/hbbs.new --perms 0755
pct push 116 /tmp/hbbr.new /usr/bin/hbbr.new --perms 0755

# 3. Стоп → swap → старт
pct exec 116 -- bash -c "
systemctl stop rustdesk-hbbs rustdesk-hbbr
mv /usr/bin/hbbs /usr/bin/hbbs.old
mv /usr/bin/hbbr /usr/bin/hbbr.old
mv /usr/bin/hbbs.new /usr/bin/hbbs
mv /usr/bin/hbbr.new /usr/bin/hbbr
systemctl start rustdesk-hbbs rustdesk-hbbr
sha256sum /var/lib/rustdesk-server/id_ed25519.pub  # проверка ключ не изменился
"

7.2 Обновление rustdesk-api (lejianwen)

# Через apt (если репо подключено) или вручную:
# 1. Скачать deb с https://github.com/lejianwen/rustdesk-api/releases
# 2. dpkg -i rustdesk-api-2.x.y.deb
# 3. Проверить config.yaml — могут добавиться новые ключи
# 4. systemctl restart rustdesk-api

7.3 Лет's Encrypt cert

Auto-renew через NPM (он сам делает). Проверка:

docker exec npm-app-1 openssl x509 -in /etc/letsencrypt/live/npm-41/fullchain.pem -noout -dates

8. Известные ограничения

  • WebClient (Flutter) не реализует full rustdesk-protocol — для рутины не используй (см. 4.3)
  • Connection from Mac→Mac не работает (peer не может быть controller'ом самого себя)
  • Strategy (config push) в /_admin/ ещё не настроена — клиенты получают конфиг через RustDesk2.toml при установке, не пушится дальше
  • Security headers в NPM не наследуются в location / (NPM template ставит add_header X-Served-By который перебивает наследование). Workaround — через more_set_headers модуль или patch NPM template. Cosmetic, не критично — TLS 1.2/1.3 + LE cert + rate-limit основной защиты.
  • apt-mark hold rustdesk-server-hbbs/hbbr — apt не обновит. Снять hold перед апгрейдом: apt-mark unhold rustdesk-server-hbbs rustdesk-server-hbbr

9. Connectivity matrix

Откуда Куда Порт Назначение
Клиент (peer) hbbs 21116/UDP rendezvous, NAT-punching
Клиент (peer) hbbs 21116/TCP id-server, heartbeat
Клиент (peer) hbbs 21115/TCP NAT-test
Клиент (peer) hbbr 21117/TCP relay для P2P
Браузер (WebClient) NPM/443 wss id-server WebSocket (через /ws/id или :21118 SSL)
Браузер (WebClient) NPM/443 wss relay WebSocket (через /ws/relay или :21119 SSL)
Админ браузер NPM/443 https /_admin/ интерфейс
Админ CLI rustdesk-api https /api/admin/login, /api/admin/...

DNS: remot.dttb.ru → public IP (через Cloudflare), внутри LAN → 10.0.0.195 (NPM).

10. Контакты на критические incidents

  • Сервер не отвечает > 10 минут → Олег батюшка
  • Все peers одновременно offline → проверить hbbs.log + LE cert + DNS
  • Брute-force попытки login (>100/час) → ban IP в NPM Access Lists или fail2ban
  • Утечка id_ed25519 → НЕМЕДЛЕННЫЙ key rotation + reinstall всех клиентов с новым RustDesk2.toml