Files
web-vnc/AGENTS.md
T
Codex 6a1ee64b14 feat(run): sync UltraVNC password from run.bat + clearer noVNC errors
- run.bat: call scripts/ensure-vnc-password.ps1 so the password typed once
  also sets the UltraVNC service VNC password (UAC only when it differs);
  skip --spawn when 5900 is already taken (don't launch a 2nd winvnc).
- scripts/ensure-vnc-password.ps1: new - compares the password against
  %ProgramData%\UltraVNC\ultravnc.ini (reverse-engineered UltraVNC DES
  obfuscation) and only writes+restarts the service when it differs.
- scripts/set-vnc-password.bat: set UltraVNC service VNC password as admin
  (createpassword/setpasswd + verify, GUI fallback). Manual fallback.
- internal/server/static/vnc.html: don't let the generic 'disconnect'
  banner overwrite the specific 'securityfailure' reason (noVNC's
  disconnect event has no reason field, so it always said 'unknown').
- AGENTS.md: document the above (scripts, run.bat, UltraVNC service note).
2026-07-30 19:15:09 +03:00

107 lines
8.9 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# AGENTS.md
Руководство для агентов (и людей), работающих с этим репозиторием.
## Сопровождение этого файла (ВАЖНО)
- **AGENTS.md должен отражать актуальное состояние кода.** Это живой документ,
а не одноразовая справка.
- При любом изменении, влияющем на: архитектуру, состав пакетов/файлов, флаги
CLI или env-переменные (`WEBVNC_*`), протокол/поведение гейтвея, скрипты,
кодировки файлов, процесс сборки/запуска или известные ограничения —
**обязательно обнови соответствующий раздел AGENTS.md в том же коммите**.
- Если заметил расхождение между AGENTS.md и реальным кодом (функция переименована,
файл удалён, флаг изменён и т.п.) — сначала приведи AGENTS.md в соответствие
с кодом, затем продолжай работу. Не оставляй устаревшие инструкции.
- Коммит, меняющий поведение/структуру, но не трогающий AGENTS.md при расхождении,
считается неполным.
## Что это
`web-vnc` — один Go-бинарник, который открывает доступ к рабочему столу (VNC)
через браузер (noVNC) с защитой по паролю. Гейтвей сам раздаёт noVNC-клиент,
проверяет пароль, ставит HMAC-сессию и прозрачно релеит WebSocket браузера в
TCP VNC-сервера (RFB). Опционально сам находит и запускает VNC-сервер.
## Ключевые принципы (НЕ нарушать)
- **Только стандартная библиотека Go.** Внешних Go-модулей нет и быть не должно —
проект собирается офлайн (в среде сборки нет интернета/Go-proxy).
WebSocket (RFC 6455) и хэш пароля (PBKDF2-HMAC-SHA256) реализованы вручную
в `internal/relay` и `internal/auth`.
- **noVNC-клиент скачивается отдельно** (`scripts/get-novnc.*`) во встроенную
статику `internal/server/static/`. Эти папки (`core/`,`app/`,`vendor/`,
`utils/`,`novnc-original.html`) в git не коммитятся (см. `.gitignore`).
Наша собственная обёртка — `internal/server/static/vnc.html` (коммитится).
- **Пароль** — один общий для всех (по требованию). Веб-пароль (PBKDF2) хранится
как `--password-hash`; тот же пароль может передаваться VNC-серверу через
`--vnc-password`/`WEBVNC_VNC_PASSWORD`, чтобы noVNC авторизовался
автоматически (одно поле ввода для пользователя).
## Сборка и запуск
```powershell
# среда без интернета: Go уже установлен, прокси недоступен -> stdlib-only
$env:GOCACHE = "$env:TEMP\go-build" # дефолтный кэш бывает без прав на запись
go build -o web-vnc.exe ./cmd/web-vnc
.\web-vnc.exe --gen-hash "пароль" # напечатает хэш
.\web-vnc.exe --password-hash <хэш> --spawn
```
Проверка: `go vet ./...`, `gofmt -l internal cmd` (должно быть пусто).
## Структура
```
cmd/web-vnc/main.go CLI: флаги, спавн VNC, запуск сервера, --gen-hash
internal/config флаги + env (WEBVNC_*)
internal/auth PBKDF2-HMAC-SHA256, HMAC session-cookie, rate-limit
internal/relay websocket.go — RFC6455 на stdlib; relay.go — WS<->TCP
internal/vncspawner кросс-ОС поиск/запуск VNC-сервера (build-теги по ОС)
internal/server HTTP-роуты, /api/status, middleware сессии, embed.FS
internal/server/static встроенные ассеты (vnc.html + noVNC core/app/vendor)
scripts/get-novnc.{ps1,sh} скачать noVNC
scripts/get-vnc.ps1 скачать портативный UltraVNC в vnc/ (с верификацией zip)
scripts/list-ips.ps1 список IPv4 машины (используется run.bat)
scripts/open-firewall.bat открыть порт 8080 в Windows Firewall (от админа)
scripts/set-vnc-password.bat задать VNC-пароль сервису UltraVNC (от админа; без него noVNC получает authentication rejected)
scripts/ensure-vnc-password.ps1 синхронизирует VNC-пароль UltraVNC с паролем из run.bat (пишет только при несовпадении; UAC только при смене) — вызывается из run.bat
run.bat запуск в один клик (спрашивает только пароль); синхронизирует VNC-пароль UltraVNC с введённым (см. ensure-vnc-password.ps1); если 5900 уже занят (сервис UltraVNC) — не порождает второй VNC-сервер, а подключается к существующему
```
## Соглашения и подводные камни
- **Кодировка файлов `.bat`:** сохранять в кодировке **cp866** с окончаниями строк
**CRLF**. PowerShell `Set-Content -Encoding UTF8` добавляет BOM и пишет LF —
не использовать для `.bat`. Пиши через
`[System.IO.File]::WriteAllText(path, content -replace "(?<!\r)\n","`r`n", [Text.Encoding]::GetEncoding(866))`.
- **Go-файлы:** UTF-8 **без BOM**, LF. То же самое правило — не использовать
`Set-Content -Encoding UTF8` (ставит BOM). Используй
`[System.IO.File]::WriteAllText(path, content, [Text.UTF8Encoding]::new($false))`.
- **`.gitignore`:** бинарники игнорируются **root-anchored** (`/web-vnc`,
`/web-vnc.exe`), иначе шаблон `web-vnc` ловит пакет `cmd/web-vnc/`.
- **vncspawner:** функции поиска VNC-сервера определены через build-теги
(`detect_windows.go`/`detect_linux.go`/`detect_darwin.go`), каждый файл
определяет `func candidates() []Candidate`. Не ссылаться на
платформо-специфичные функции из общих файлов.
- **Тесты в этой среде:** интернет отсутствует; проверяй через локальные
заглушки (TCP-эхо-сервер на 5900, `Get-NetIPAddress` часто пуст —
`list-ips.ps1` имеет фолбэк на `ipconfig`). Запущенный web-vnc.exe из
фонового job может остаться «зомби» (Stop-Process иногда access denied);
используй разные порты для тестов и по возможности запускай killable-способом.
- **Hijack WebSocket:** `internal/relay` сам делает апгрейд через
`http.Hijacker`; гейтвей НЕ использует gorilla/websocket.
## Что делать дальше (известные TODO)
- Надёжный авто-скачиватель VNC-сервера (URL UltraVNC на SourceForge нестабилен —
`get-vnc.ps1` теперь верифицирует zip-магию и даёт фолбэк на ручную установку).
- На Windows захват экрана может требовать запуск VNC-сервера от администратора.
- VNC-сервер требует свой пароль; `--vnc-password` передаёт его noVNC
автоматически, но пароль VNC-сервера нужно один раз настроить под тот же.
**UltraVNC как сервис (`uvnc_service`, LocalSystem):** пароль хранится в
`%ProgramData%\UltraVNC\ultravnc.ini`; задать его обычным пользователем через
tray-иконку молча не получается (нет прав на запись).
`run.bat` синхронизирует этот пароль сам через `scripts/ensure-vnc-password.ps1`
(пишет только при несовпадении, UAC только при смене; вручную — `scripts/set-vnc-password.bat` от админа). VNC-пароль = первые 8 байт,
поэтому используй ASCII-пароль <= 8 символов и там, и в `run.bat`.