autostart-run.bat did 'cd /d %~dp0' -> scripts/, but web-vnc.exe/webvnc.conf/ go.mod live in the repo root, so the binary was never found and web-vnc never started after reboot. Now it cd's to %~dp0.. (repo root). The task was ONSTART/RU SYSTEM (session 0) so it could not show a window, making failures invisible. install-autostart.bat now registers ONLOGON /RL HIGHEST as the current user -> a visible console opens at logon. autostart-run.bat sets a window title, prints status, stays open while web-vnc serves, and pauses on fatal errors (no binary / no webvnc.conf) so the reason is visible. Docs updated.
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 без запросов.
-
Один раз задайте пароль:
set-password.batСпросит пароль доступа, сгенерирует хэш и сохранит его вместе с паролем в
webvnc.conf(секрет, в git не коммитится), а затем синхронизирует им пароль UltraVNC-сервиса (scripts\ensure-vnc-password.ps1, UAC только при смене). Веб-пароль оказывается настроен, даже если синк UltraVNC упадёт или UAC отменят. Используйте ASCII-пароль длиной до 8 символов (VNC-пароль = первые 8 байт). -
Запустите gateway:
run.batrun.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
install-autostart.bat :: один раз (от админа): плановое задание «web-vnc»
install-autostart.bat регистрирует через schtasks задание (ONLOGON, HIGHEST,
от имени текущего пользователя), которое при входе в систему открывает видимую
консоль с scripts\autostart-run.bat — launcher, читающий webvnc.conf, ждущий
127.0.0.1:5900 до ~30 c и затем запускающий web-vnc.exe (не качает ничего на старте).
Окно остаётся, пока web-vnc работает; при ошибке — пауза, чтобы было видно причину.
Запуск от SYSTEM/ONSTART не используется: он в session 0 и окна не показывает.
Запустить сразу без перезагрузки: schtasks /Run /TN "web-vnc".
Снять автостарт: uninstall-autostart.bat (от админа).
Смена пароля: web-vnc.exe читает пароль из webvnc.conf только при старте и не
перечитывает его в runtime. Поэтому set-password.bat (если задание «web-vnc» установлено)
перезапускает его через 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
Как это работает
- Пользователь открывает
http://хост:8080/и попадает на/login. - Вводит общий пароль. Он сверяется с солёным PBKDF2-HMAC-SHA256-хэшем (120 000 итераций). При успехе сервер ставит HMAC-подписанную, HttpOnly-куку сессии (по умолчанию 8 ч, без серверного хранилища).
- Браузер загружает
/vnc.html(только с валидной сессией). Клиент noVNC открывает WebSocket на/vnc. 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: установите UltraVNC или TightVNC, либо запустите
-
С другого компьютера страница не открывается (таймаут/недоступно). По умолчанию Windows Firewall блокирует входящие подключения. Один раз выполните от имени администратора:
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)
Пользовательские точки входа — в корне репозитория:
run.bat интерактивный запуск: собирает бинарник/noVNC/VNC, читает пароль из webvnc.conf (не спрашивает)
set-password.bat разовая настройка пароля -> webvnc.conf (хэш + VNC-пароль); синхронизирует UltraVNC
install-autostart.bat автостарт при входе (schtasks ONLOGON/HIGHEST, видимая консоль) — от админа
uninstall-autostart.bat снять автостарт — от админа
restart-autostart.bat перезапустить задание «web-vnc» (чтобы применить новый пароль) — от админа
open-firewall.bat открыть порт 8080 в Windows Firewall (один раз, от админа)
webvnc.conf секрет: HASH= + VNC_PASSWORD= (создаётся set-password.bat, gitignored)
Внутренние помощники — в scripts/ (вызываются другими скриптами):
scripts/autostart-run.bat launcher автостарта (видимая консоль): cd в корень репо, читает webvnc.conf, ждёт 5900 до ~30 c, запускает web-vnc (без --spawn, если VNC уже слушает); pause на ошибке
scripts/ensure-vnc-password.ps1 синхронизирует VNC-пароль UltraVNC (вызывается из set-password.bat)
scripts/get-novnc.{ps1,sh} скачать noVNC во встроенную статику
scripts/get-vnc.ps1 скачать портативный VNC-сервер (UltraVNC) в папку vnc/
scripts/list-ips.ps1 список IPv4 машины (используется run.bat)
Кросс-компиляция под другую ОС
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.