feat: web-vnc single-binary browser VNC gateway with password access
- Go stdlib-only gateway: serves noVNC client, password auth, WS<->TCP relay - auth: PBKDF2-HMAC-SHA256 password hash, HMAC session cookies, login rate limit - relay: hand-written RFC 6455 WebSocket + transparent RFB bridge - vncspawner: cross-OS VNC server detection/launch (Windows/Linux/macOS) - server: /login /logout /vnc /api/status routes, session middleware, embed.FS - scripts: get-novnc, get-vnc (zip-verified), list-ips, open-firewall - run.bat: one-click launcher (asks only password), lists access IPs - README/AGENTS.md (Russian), .gitignore (root-anchored binaries)
This commit is contained in:
@@ -0,0 +1,85 @@
|
||||
# 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 (от админа)
|
||||
run.bat запуск в один клик (спрашивает только пароль)
|
||||
```
|
||||
|
||||
## Соглашения и подводные камни
|
||||
|
||||
- **Кодировка файлов `.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-сервера нужно один раз настроить под тот же.
|
||||
Reference in New Issue
Block a user