From d58873368a888654a1871b28ab91fceb847e7dc1 Mon Sep 17 00:00:00 2001 From: dttb Date: Thu, 30 Apr 2026 10:42:19 +0300 Subject: [PATCH] =?UTF-8?q?RustDesk:=20pre-prod=20security=20audit=20+=20?= =?UTF-8?q?=D0=BE=D0=BF=D0=B5=D1=80=D0=B0=D1=86=D0=B8=D0=BE=D0=BD=D0=BD?= =?UTF-8?q?=D1=8B=D0=B9=20runbook?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Аудит перед запуском в прод. Найдены и исправлены 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) --- .../2026-04-30-rustdesk-pre-prod-audit.md | 192 ++++++++++ projects/dttb/rustdesk-runbook.md | 347 ++++++++++++++++++ projects/dttb/rustdesk.md | 12 + 3 files changed, 551 insertions(+) create mode 100644 decisions/2026-04-30-rustdesk-pre-prod-audit.md create mode 100644 projects/dttb/rustdesk-runbook.md diff --git a/decisions/2026-04-30-rustdesk-pre-prod-audit.md b/decisions/2026-04-30-rustdesk-pre-prod-audit.md new file mode 100644 index 0000000..cde01fc --- /dev/null +++ b/decisions/2026-04-30-rustdesk-pre-prod-audit.md @@ -0,0 +1,192 @@ +--- +date: 2026-04-30 +type: audit +tags: [rustdesk, security, audit, hardening] +--- + +# RustDesk pre-production audit + fixes + +## Контекст + +Перед запуском RustDesk-сервера в продакшн (для удалённого доступа клиентских организаций + личного использования) — системный аудит security, reliability, operations. Findings + примененные fixes. + +## Findings & fixes + +### 🔴 Critical (исправлено) + +#### 1. Права на критичные файлы 644 → 600/640 + +**Что было:** все sensitive файлы на LXC 116 были world-readable (`-rw-r--r--`): +- `/var/lib/rustdesk-server/id_ed25519` (**приватный ключ сервера**) +- `/var/lib/rustdesk-server/id_ed25519.pub` +- `/var/lib/rustdesk-server/db_v2.sqlite3*` (hbbs БД с peers UUID) +- `/var/lib/rustdesk-api/data/rustdeskapi.db` (хеши паролей юзеров, токены сессий) +- `/var/lib/rustdesk-api/conf/config.yaml` (содержит **JWT secret** и `key`) + +**Риск:** при компрометации любого non-root юзера на LXC 116 → leak приватного ключа сервера → весь парк клиентов перестаёт быть приватным; возможность подделки JWT и login as admin. + +**Fix (2026-04-30):** +```bash +chmod 600 /var/lib/rustdesk-server/id_ed25519* +chmod 640 /var/lib/rustdesk-server/db_v2.sqlite3* +chmod 640 /var/lib/rustdesk-api/data/rustdeskapi.db +chmod 640 /var/lib/rustdesk-api/conf/config.yaml +``` + +#### 2. Нет logrotate для rustdesk-логов на 2GB-диске + +**Что было:** `/var/log/rustdesk-server/hbbs.log` ~260KB и rosт каждый день. На 2GB-диске LXC 116 (где уже 55% used) логи зальют диск за пару месяцев → сервер ляжет. + +**Fix (2026-04-30):** `/etc/logrotate.d/rustdesk`: +``` +/var/log/rustdesk-server/*.log /var/log/rustdesk-server/*.error +/var/log/rustdesk-api/*.log /var/log/rustdesk-api/*.error { + daily + rotate 14 + compress + delaycompress + notifempty + missingok + copytruncate + su root root +} +``` + +#### 3. Нет авто-бэкапа БД и ключей + +**Что было:** одна вручную сделанная копия `/root/rustdesk-backup-20260428-1134/`. Если завтра LVM упадёт — теряем весь стейт (peers, users, ключи). + +**Fix (2026-04-30):** cron daily 03:00 → `/usr/local/bin/rustdesk-backup.sh`: +- tar.gz в `/root/rustdesk-backups/rustdesk-YYYYMMDD.tar.gz` +- ключи + обе БД + config.yaml + systemd overrides +- retention 30 дней (find -mtime +30 -delete) +- chmod 600 на каждый tarball + +**TODO:** доставить копии бэкапа на ArtLeon (off-site) через NetBird/rsync. + +### 🟡 Medium (исправлено) + +#### 4. Нет rate-limit на login → brute-force admin password + +**Что было:** `https://remot.dttb.ru/api/admin/login` принимал безlimit запросы. С учётом стандартного pw `1qaz!QAZ` — кто-то с словарём найдёт его за час. + +**Fix (2026-04-30):** в NPM `/data/compose/2/data/nginx/custom/http.conf`: +```nginx +limit_req_zone $binary_remote_addr zone=adminlogin:10m rate=5r/m; +limit_req_zone $binary_remote_addr zone=apilogin:10m rate=10r/m; +``` + +В Proxy Host 14 advanced_config: +```nginx +location = /api/admin/login { + limit_req zone=adminlogin burst=3 nodelay; + proxy_pass http://10.0.0.244:21114; + ... +} +location = /api/login { + limit_req zone=apilogin burst=5 nodelay; + proxy_pass http://10.0.0.244:21114; + ... +} +``` + +**Verified:** после 4 быстрых попыток — 503 от NPM. На уровне rustdesk-api также `ban-threshold: 5` забанит user-account на ~1 час. + +**Грабли при настройке:** `limit_req_zone` нельзя класть в `server`-контекст — только `http`. Первая попытка положить в advanced_config привела к удалению NPM proxy_host/14.conf и обвалу `remot.dttb.ru`. Восстановилось через disable/enable + переноса zone в http.conf. + +### 🟡 Medium (отложено) + +#### 5. NC public-link без пароля + содержит RustDesk2.toml с key + +**Что было:** `https://dttb.ru/s/wPm8oaiFEyz7Ywx` без пароля и без expiration. ZIP внутри содержит `key=R0lA4r77...`. Любой нашедший ссылку может зарегистрировать peer'а на нашем сервере. + +**Status:** **Nextcloud-AIO сейчас лежит** (502 from NPM upstream), новую share создать не получается. Спавнен отдельный task на восстановление NC. После — пересоздать share с паролем + 30 дней expiration. + +**Митigation в текущем виде:** `MUST_LOGIN=Y` отбивает входящие connections к незалогиненным peers. Кто-то регистрируется как peer — heartbeat-флуд возможен, но connections не пройдут. + +#### 6. Security headers не наследуются в location / + +**Что было:** HSTS, X-Frame-Options, X-Content-Type-Options, Referrer-Policy не появляются в response от `https://remot.dttb.ru/_admin/`. + +**Корневая причина:** NPM в template для Proxy Host генерит `location /` со встроенным `add_header X-Served-By` (через include `proxy.conf`). По правилу nginx — если в location есть **хоть один** add_header, наследование от server-block отключается. Мои `add_header` в advanced_config (server-level) не применяются к location /. + +**Fix-варианты (выбран wait):** +- (a) Patch NPM template `/etc/nginx/conf.d/include/proxy.conf` чтобы добавить headers — теряется при container recreate +- (b) Использовать `more_set_headers` (модуль ngx_headers_more) — нужно проверить что он есть в openresty +- (c) Override `location /` в advanced_config с явными add_header — конфликт с NPM-сгенерированным location / +- (d) **Принять как cosmetic** — TLS 1.2/1.3 + LE cert + rate-limit обеспечивают основную защиту; HSTS на server-level записан в nginx.conf (не на response). + +**Status:** **отложено** как cosmetic. Если будем делать (b) или (a) — отдельной задачей. + +### 🟢 Low / Informational + +| Item | Status | +|---|---| +| Server header раскрывает `openresty` | Accept (мелкий fingerprinting, не критично) | +| `show-swagger: 1` в API | Accept (Олег использует для разработки) | +| TLS 1.2 + 1.3, intermediate ciphers | ✅ optimal | +| LE cert valid until 28 June 2026 | ✅ auto-renew | +| Block Common Exploits (NPM) | ✅ enabled на host 14 | +| `block_exploits: true`, `caching_enabled: false` | ✅ verified | +| `register: false` в API | ✅ закрытая система | +| `ban-threshold: 5`, `captcha-threshold: 3` | ✅ enabled | +| `MUST_LOGIN=Y` | ✅ enforced (видно в hbbs.log) | +| RustDesk peers версии | 1.4.6 (latest stable) | +| Disk LXC 116 free | 826 MB / 2 GB (55% used) — monitoring | +| RAM LXC 116 used | 105M / 512M — большой запас | +| NPM compose ports 21115-21119 | ✅ exposed после 2026-04-29 update | + +## Что осталось сделать (production todo) + +### Перед массовым deploy +- [ ] Восстановить Nextcloud (отдельный task) +- [ ] Создать share-link с паролем + expiration после восстановления NC +- [ ] Создать минимум 2 группы в `/_admin/` (например `НИИКН`, `Клиенты-Internal`) +- [ ] Настроить **Configuration Strategy** в админке lejianwen — push настроек существующим клиентам автоматически +- [ ] Off-site бэкап `/root/rustdesk-backups/*.tar.gz` на ArtLeon через rsync over NetBird (cron weekly) + +### Полезное (не блокирует prod) +- [ ] `more_set_headers` фикс security headers +- [ ] fail2ban на NPM access logs (поверх rate-limit) — extra слой против distributed brute-force +- [ ] Monitoring: alert на падение rustdesk сервиса (через watchyourlan/zabbix/uptime-kuma) +- [ ] Auto-login клиента в API через service-token (упрощает onboarding) +- [ ] `rustdesk-utils` 2.x для single-file `rustdesk-licensed-*.exe` deployment + +### Долгосрочное +- [ ] Через 1-2 месяца — миграция в Docker `lejianwen/rustdesk-server-s6` (Вариант A3) +- [ ] HA-схема на втором экземпляре (НИИКН Proxmox) с общей MySQL +- [ ] MCP-обёртка поверх Swagger API для управления из Claude Code + +## Верификация + +```bash +# Permissions OK +ssh root@10.0.0.250 "pct exec 116 -- ls -la /var/lib/rustdesk-server/id_ed25519" +# → -rw------- 1 root root 88 Oct 10 2025 + +# Logrotate OK +ssh root@10.0.0.250 "pct exec 116 -- logrotate -d /etc/logrotate.d/rustdesk" +# → "considering log /var/log/rustdesk-..." + +# Auto-backup ran +ssh root@10.0.0.250 "pct exec 116 -- ls -la /root/rustdesk-backups/" +# → rustdesk-20260430.tar.gz + +# Rate-limit работает +for i in {1..6}; do + curl -ks -o /dev/null -w "%{http_code} " -X POST https://remot.dttb.ru/api/admin/login \ + -H "Content-Type: application/json" -d '{"username":"x","password":"y"}' +done +# → 200 200 200 200 503 503 + +# Сервер отвечает +curl -ksI https://remot.dttb.ru/_admin/ | head -1 +# → HTTP/2 200 +``` + +## Связанные + +- [[../projects/dttb/rustdesk-runbook]] — операционный runbook (создан этим audit'ом) +- [[2026-04-28-rustdesk-lejianwen-pro-migration]] — миграция с OSS +- [[2026-04-29-rustdesk-client-deployment-package]] — пакет установки клиентов +- [[../projects/dttb/rustdesk]] — справочник diff --git a/projects/dttb/rustdesk-runbook.md b/projects/dttb/rustdesk-runbook.md new file mode 100644 index 0000000..568f8b2 --- /dev/null +++ b/projects/dttb/rustdesk-runbook.md @@ -0,0 +1,347 @@ +--- +date: 2026-04-30 +type: runbook +tags: [rustdesk, runbook, operations, recovery, troubleshooting] +--- + +# RustDesk Server — Operational Runbook + +Операционная инструкция для повседневной эксплуатации, troubleshooting и recovery. + +Связанные документы: +- [[rustdesk]] — справочник по серверу +- [[../../decisions/2026-04-28-rustdesk-lejianwen-pro-migration]] — история миграции с OSS +- [[../../decisions/2026-04-29-rustdesk-client-deployment-package]] — пакет установки клиентов +- [[../../decisions/2026-04-30-rustdesk-pre-prod-audit]] — pre-production audit + fixes +- [[credentials#RustDesk Server (LXC 116)]] — креды + +--- + +## 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 Проверить здоровье сервера + +```bash +# С 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 онлайн) + +```bash +# 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 смена пароля: +```bash +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 '" +``` + +## 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-.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>` / ``) + - Без login: `MUST_LOGIN=Y` отбрасывает входящие connections — peer виден как online но connect к нему отказан +6. **Админ в `/_admin/`** → Devices → находит peer ID → привязывает к нужной группе + +### 3.3 Создание public-link на установщик + +```bash +# Через 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/` не отвечает + +```bash +# 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?** + ```bash + 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='';\"" + ``` + Если **пусто** → клиент не логинился через 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 + +```bash +# Например, восстановить состояние на 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. + +```bash +# 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) + +```bash +# Через 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 (он сам делает). +Проверка: +```bash +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` diff --git a/projects/dttb/rustdesk.md b/projects/dttb/rustdesk.md index 7edd3af..5db2284 100644 --- a/projects/dttb/rustdesk.md +++ b/projects/dttb/rustdesk.md @@ -136,6 +136,18 @@ tail -f /var/log/rustdesk-api/rustdesk-api.log - `/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]].