Files
web-vnc/README.md
T
Codex 754f77a8d0 feat: autostart as a service + separate password setup (set-password.bat)
- set-password.bat: one-time password setup -> writes webvnc.conf (HASH + VNC_PASSWORD), syncs UltraVNC via ensure-vnc-password.ps1; if the 'web-vnc' task is installed, restarts it (elevated) to reload the new password, skipping restart when the password is unchanged.
- run.bat: no longer prompts for the password; reads it from webvnc.conf (asks to run set-password.bat first if absent). Also clears --spawn-command (not just --spawn) when 5900 is already listening, to avoid spawning a 2nd VNC server.
- scripts/autostart-run.bat: non-interactive launcher for the scheduled task (reads webvnc.conf, finds only a LOCAL VNC server, never downloads at boot).
- scripts/install-autostart.bat / uninstall-autostart.bat: register/remove a 'web-vnc' scheduled task (ONSTART, SYSTEM, HIGHEST) via schtasks.
- scripts/restart-autostart.bat: restart the task to apply a new password; checks whether web-vnc.exe is running (stop+start, or just start).
- .gitignore: ignore webvnc.conf (secret).
- AGENTS.md / README.md: document the autostart flow, set-password.bat, the new scripts, and that the running gateway must be restarted to apply a password change.
2026-08-05 15:23:58 +03:00

15 KiB
Raw Blame History

web-vnc

Один бинарник, который открывает доступ к рабочему столу (VNC) через браузер (noVNC) с защитой по паролю. Программа web-vnc:

  • раздаёт HTML5-клиент noVNC,
  • пускает зрителя по общему паролю,
  • прокидывает WebSocket браузера к локальному VNC-серверу (RFB поверх WS),
  • и (по желанию) сама запускает VNC-сервер.

Написано на чистом Go, только стандартная библиотека — никаких внешних Go-модулей, собирается офлайн.

 Браузер (noVNC)  ──ws──▶  web-vnc (один бинарник)  ──tcp RFB──▶  VNC-сервер (127.0.0.1:5900)
                            ├─ вход по паролю (PBKDF2-HMAC-SHA256)
                            ├─ HMAC session-cookie
                            └─ прозрачный релей WS↔TCP

Самый простой запуск (Windows)

Запуск состоит из двух шагов: один раз задаётся пароль, затем run.bat поднимает gateway без запросов.

  1. Один раз задайте пароль:

    set-password.bat
    

    Спросит пароль доступа, синхронизирует им пароль UltraVNC-сервиса (scripts\ensure-vnc-password.ps1, UAC только при смене), сгенерирует хэш и сохранит его вместе с паролем в webvnc.conf (секрет, в git не коммитится). Используйте ASCII-пароль длиной до 8 символов (VNC-пароль = первые 8 байт).

  2. Запустите gateway:

    run.bat
    

    run.bat собирает web-vnc.exe (нужен Go, если бинарника нет), встраивает noVNC-клиент (качает при наличии интернета), находит/докачивает VNC-сервер, читает пароль из webvnc.conf (больше не спрашивает), печатает адреса (http://localhost:8080 и http://<каждый IPv4 машины>:8080) и запускает сервер с флагом --spawn. Если 127.0.0.1:5900 уже слушает (сервис UltraVNC) — запускается без --spawn, подключаясь к существующему серверу.

После запуска откройте в браузере один из выведенных адресов, введите тот же пароль — и попадёте на рабочий стол.

Автостарт при загрузке ОС (вместо ручного run.bat)

set-password.bat                 :: один раз: пароль -> webvnc.conf
scripts\install-autostart.bat    :: один раз (от админа): плановое задание «web-vnc»

install-autostart.bat регистрирует через schtasks задание (ONSTART, SYSTEM, HIGHEST), которое при загрузке запускает scripts\autostart-run.bat — неинтерактивный launcher, читающий webvnc.conf и не качающий ничего на старте. Запустить сразу без перезагрузки: schtasks /Run /TN "web-vnc". Снять автостарт: scripts\uninstall-autostart.bat (от админа).

Смена пароля: web-vnc.exe читает пароль из webvnc.conf только при старте и не перечитывает его в runtime. Поэтому set-password.bat (если задание «web-vnc» установлено) перезапускает его через scripts\restart-autostart.bat (с elevation) — тот проверяет, запущен ли web-vnc.exe (если да — стоп + старт, если нет — только старт). Рестарт пропускается, если пароль не изменился. Для интерактивного run.bat просто перезапустите его вручную.

Быстрый старт вручную (Windows)

# 1. Подтянуть noVNC-клиент во встроенную статику (один раз)
.\scripts\get-novnc.ps1

# 2. Собрать бинарник
go build -o web-vnc.exe .\cmd\web-vnc

# 3. Сгенерировать хэш пароля
$hash = .\web-vnc.exe --gen-hash "ваш-пароль"

# 4. Запустить (сам найдёт/запустит VNC-сервер и поднимется на :8080)
.\web-vnc.exe --password-hash $hash --spawn

Быстрый старт (Linux / macOS)

./scripts/get-novnc.sh
go build -o web-vnc ./cmd/web-vnc
hash=$(./web-vnc --gen-hash "ваш-пароль")
./web-vnc --password-hash "$hash" --spawn

Как это работает

  1. Пользователь открывает http://хост:8080/ и попадает на /login.
  2. Вводит общий пароль. Он сверяется с солёным PBKDF2-HMAC-SHA256-хэшем (120 000 итераций). При успехе сервер ставит HMAC-подписанную, HttpOnly-куку сессии (по умолчанию 8 ч, без серверного хранилища).
  3. Браузер загружает /vnc.html (только с валидной сессией). Клиент noVNC открывает WebSocket на /vnc.
  4. web-vnc проверяет сессию до апгрейда WebSocket и затем прозрачно релеит байты между WebSocket и локальным VNC-сервером (127.0.0.1:5900 по умолчанию). RFB-протокол проходит нетронутым, как у websockify.

VNC-сервер должен слушать на loopback (127.0.0.1) и может работать без VNC-пароля — защита по паролю теперь на веб-гейтвее. Если же ваш VNC-сервер требует свой пароль, noVNC спросит и его.

Авто-запуск VNC-сервера (--spawn)

С --spawn программа ищет установленный VNC-сервер и запускает его как дочерний процесс (отдельно, без окна на Windows), после чего подключается к нему.

ОС Что ищет
Windows UltraVNC (winvnc.exe), TightVNC (tvnserver.exe)
Linux x11vnc, tigervncserver / Xvnc
macOS встроенный Screen Sharing (kickstart)

Переопределить авто-поиск своей командой:

.\web-vnc.exe --password-hash $hash --spawn-command "C:\Path\To\winvnc.exe -run"

Без --spawn убедитесь, что VNC-сервер уже слушает по адресу из --vnc.

Настройка

Все флаги дублируются переменными окружения (WEBVNC_*).

Флаг Env По умолчанию Описание
--listen WEBVNC_LISTEN :8080 адрес HTTP/WS
--vnc WEBVNC_VNC 127.0.0.1:5900 адрес вышестоящего VNC-сервера
--password-hash WEBVNC_PASSWORD_HASH (обязателен) хэш PBKDF2 из --gen-hash
--session-secret WEBVNC_SESSION_SECRET случайный при старте HMAC-ключ для подписи куки сессии
--session-ttl WEBVNC_SESSION_TTL 8h время жизни куки сессии
--spawn WEBVNC_SPAWN false авто-запуск найденного VNC-сервера
--spawn-command WEBVNC_SPAWN_COMMAND (нет) явная команда запуска VNC-сервера
--web-root WEBVNC_WEB_ROOT (встроенные) раздавать статику с диска вместо embed
--novnc-path /vnc.html путь страницы noVNC-клиента
--relay-path /vnc endpoint WebSocket-релея

Сгенерировать хэш пароля

web-vnc --gen-hash "ваш-пароль"
# напечатает, например:  pbkdf2-sha256$120000$<соль>$<ключ>

Формат самодокументируемый: pbkdf2-sha256$<итерации>$<base64-соль>$<base64-ключ>.

Запуск одной строкой

.\web-vnc.exe --password-hash (. \web-vnc.exe --gen-hash "secret") --spawn

Безопасность

  • Без TLS: рассчитано на приватную сеть. Если выставляете наружу — поставьте перед ним reverse-proxy с TLS (nginx/caddy).
  • Логин с лимитом попыток (5 в минуту на IP, в памяти).
  • Кука сессии подписана --session-secret. Задайте фиксированный --session-secret, чтобы сессии переживали перезапуск (иначе секрет меняется при каждом старте, и старые сессии инвалидируются).
  • VNC-сервер держите на 127.0.0.1, чтобы до него нельзя было достучаться в обход гейтвея.

Устранение неполадок

  • После ввода пароля — ошибка / нет картинки. Значит, веб-гейтвей не смог подключиться к VNC-серверу (по адресу --vnc, по умолчанию 127.0.0.1:5900). На странице теперь показывается понятное сообщение вместо криптографической ошибки noVNC. Решение: должен работать VNC-сервер, который отдаёт рабочий стол:

    • Windows: установите UltraVNC или TightVNC, либо запустите scripts\get-vnc.ps1 (скачает портативный UltraVNC в папку vnc\, и run.bat сам его запустит).
    • Linux: x11vnc или TigerVNC.
    • macOS: встроенный Screen Sharing. Важно: VNC-сервер должен слушать на 127.0.0.1:5900. На Windows для захвата экрана может потребоваться запуск от имени администратора (UAC).
  • С другого компьютера страница не открывается (таймаут/недоступно). По умолчанию Windows Firewall блокирует входящие подключения. Один раз выполните от имени администратора:

    scripts\open-firewall.bat
    

    Это откроет входящий TCP-порт 8080. (run.bat выводит адреса и подсказку.)

  • noVNC-клиент не встроен (страница-заглушка). Запустите scripts\get-novnc.ps1 (нужен интернет), пересоберите и перезапустите.

Структура проекта

cmd/web-vnc/main.go        точка входа CLI: флаги, спавн VNC, запуск сервера
internal/config            конфигурация (флаги + env)
internal/auth              хэш пароля PBKDF2, HMAC-куки сессии, rate-limit
internal/relay             WebSocket на stdlib (RFC 6455) + мост WS↔TCP
internal/vncspawner        кросс-ОС поиск и запуск VNC-сервера
internal/server            HTTP-роуты, middleware сессии, встроенная статика
internal/server/static     встроенные веб-ассеты (vnc.html + core/app/vendor noVNC)
scripts/get-novnc.{ps1,sh} скачать noVNC во встроенную статику
scripts/get-vnc.ps1       скачать портативный VNC-сервер (UltraVNC) в папку vnc/
scripts/list-ips.ps1       список IPv4 машины (используется run.bat)
scripts/open-firewall.bat открыть порт 8080 в Windows Firewall (один раз, от админа)
run.bat                    интерактивный запуск: собирает бинарник/noVNC/VNC, читает пароль из webvnc.conf (не спрашивает)
set-password.bat           разовая настройка пароля -> webvnc.conf (хэш + VNC-пароль); синхронизирует UltraVNC
webvnc.conf                секрет: HASH= + VNC_PASSWORD= (создаётся set-password.bat, gitignored)
scripts/autostart-run.bat  неинтерактивный launcher для автостарта (читает webvnc.conf)
scripts/install-autostart.bat  автостарт при загрузке ОС (schtasks ONSTART/SYSTEM) — от админа
scripts/uninstall-autostart.bat снять автостарт — от админа
scripts/restart-autostart.bat перезапустить задание «web-vnc» (чтобы применить новый пароль) — от админа

Кросс-компиляция под другую ОС

GOOS=linux   GOARCH=amd64 go build -o web-vnc-linux   ./cmd/web-vnc
GOOS=windows GOARCH=amd64 go build -o web-vnc.exe     ./cmd/web-vnc
GOOS=darwin  GOARCH=arm64 go build -o web-vnc-macos   ./cmd/web-vnc

Лицензия

MIT. Встроенные ассеты noVNC сохраняют свою лицензию (MPL-2.0) — см. internal/server/static/LICENSE после запуска get-novnc.