- 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).
8.9 KiB
8.9 KiB
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 авторизовался автоматически (одно поле ввода для пользователя).
Сборка и запуск
# среда без интернета: 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. PowerShellSet-Content -Encoding UTF8добавляет BOM и пишет LF — не использовать для.bat. Пиши через[System.IO.File]::WriteAllText(path, content -replace "(?<!\r)\n","rn", [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.