diff --git a/AGENTS.md b/AGENTS.md index f2fa70f..93657d7 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -58,7 +58,7 @@ 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) +internal/server/static встроенные ассеты (vnc.html, favicon.ico + noVNC core/app/vendor) scripts/get-novnc.{ps1,sh} скачать noVNC scripts/get-vnc.ps1 скачать портативный UltraVNC в vnc/ (с верификацией zip) scripts/list-ips.ps1 список IPv4 машины (используется run.bat) @@ -92,6 +92,23 @@ run.bat запуск в один клик (спрашивае `list-ips.ps1` имеет фолбэк на `ipconfig`). Запущенный web-vnc.exe из фонового job может остаться «зомби» (Stop-Process иногда access denied); используй разные порты для тестов и по возможности запускай killable-способом. +- **favicon.ico:** браузер запрашивает `/favicon.ico` на каждой странице + (включая форму логина). Роут `/favicon.ico` зарегистрирован **вне** session- + middleware (чтобы без сессии не редиректил на /login и не давал 404) и отдаёт + встроенный `internal/server/static/favicon.ico` (иконка-монитор, коммитится; + не входит в скачиваемые noVNC-ассеты). На логине и vnc.html есть + ``. +- **Secure context (TLS) в noVNC:** noVNC (`core/rfb.js`, `app/ui.js`) печатает + `Log.Error("noVNC requires a secure context (TLS). Expect crashes!")` при + `!window.isSecureContext` — т.е. на plain-http по LAN-IP. Для обычной VNC- + password-авторизации это **безобидно**: noVNC использует чистый-JS DES из + `core/des.js` и НЕ нуждается в `crypto.subtle`. Чтобы не пугать пользователя + красной ошибкой в консоли, обёртка `vnc.html` ДО импорта `core/rfb.js` + оборачивает `console.error` фильтром, гасящим **только** эту строку (всё + остальное проходит в оригинальный `console.error`). Файлы noVNC (core/, app/, + …) НЕ правятся — они gitignored и перезаливаются `scripts/get-novnc.*`. + Корректный способ сделать контекст действительно secure — HTTPS (self-signed), + но это отдельная фича; пока — фильтр в vnc.html. - **Hijack WebSocket:** `internal/relay` сам делает апгрейд через `http.Hijacker`; гейтвей НЕ использует gorilla/websocket. diff --git a/internal/server/server.go b/internal/server/server.go index 1cec066..22eeb8f 100644 --- a/internal/server/server.go +++ b/internal/server/server.go @@ -58,6 +58,11 @@ func (s *Server) Handler() http.Handler { mux.Handle(s.cfg.RelayPath, s.requireSession(http.HandlerFunc(s.handleRelay))) mux.Handle(s.cfg.NoVNCPath, s.requireSession(http.HandlerFunc(s.serveNoVNCPage))) + + // favicon is fetched by the browser on every page (incl. the login form); + // serve it without a session so it doesn't redirect to /login and 404. + mux.HandleFunc("/favicon.ico", s.handleFavicon) + mux.Handle("/", s.requireSession(http.HandlerFunc(s.handleIndexOrStatic))) return s.logRequest(mux) @@ -110,6 +115,19 @@ func (s *Server) handleRelay(w http.ResponseWriter, r *http.Request) { s.relay.ServeHTTP(w, r) } +// handleFavicon serves the embedded favicon.ico with a long cache. It is +// registered outside requireSession so it loads on the login page too. +func (s *Server) handleFavicon(w http.ResponseWriter, r *http.Request) { + data, err := fs.ReadFile(s.static, "favicon.ico") + if err != nil { + http.NotFound(w, r) + return + } + w.Header().Set("Content-Type", "image/x-icon") + w.Header().Set("Cache-Control", "public, max-age=604800") + _, _ = w.Write(data) +} + func (s *Server) serveNoVNCPage(w http.ResponseWriter, r *http.Request) { if data, err := fs.ReadFile(s.static, "vnc.html"); err == nil { w.Header().Set("Content-Type", "text/html; charset=utf-8") diff --git a/internal/server/static/favicon.ico b/internal/server/static/favicon.ico new file mode 100644 index 0000000..7f167d6 Binary files /dev/null and b/internal/server/static/favicon.ico differ diff --git a/internal/server/static/vnc.html b/internal/server/static/vnc.html index 3c1cde6..c0497b9 100644 --- a/internal/server/static/vnc.html +++ b/internal/server/static/vnc.html @@ -4,6 +4,7 @@