packages/dsh-remote-web-ui
zhu1090093659/dsh-web手机/PC 远程操控 dsh web 工作区:扫码配对、令牌门控通道、SSE 实时同步,提供移动端与完整桌面 GUI 两种远程形态。
局域网访问 dsh web UI:HTTP/HTTPS/WS 转发 + TLS(自签名/自定义证书);HTTP 自适应 Brotli/gzip 与 WebSocket permessage-deflate 双压缩;WS 半开探活,移动端切后台不僵死;启动令牌自动注入,LAN 设备免手工拿 token;DNS 重绑定防护 + 回环-only 上游白名单。
局域网访问 dsh web UI:在 0.0.0.0: 监听,把 HTTP/HTTPS 与 WebSocket/wss 转发到回环 web 服务器(默认 127.0.0.1:3080)。
简体中文 | English
dsh plugin --profile web add @wingsky-1/dsh-lan-proxy安装 / 卸载 / 更新后都需重启一次 dsh web(bundle 层只在启动时组合)生效。使用前须知 · 安全模型 · 最短上手 · 常用配置 · 验证与排障 · 详细参考 · 开发与架构
前提:已安装 DeepSeek Harness 且 dsh web 可正常启动(未全局安装 dsh 见下方「未全局安装 dsh」)。
targetHost 仅允许回环地址(localhost / 127.0.0.1 /::1),配置层与运行时入口双重校验——防止开放转发/SSRF
localhost 的请求,域名一律403/断开;IP 字面量在任何端口都安全
浏览器信任围栏内可读写服务器 settings(含凭据类数据)——确保你的局域网 可信,或禁用该插件
0.1.2 起 /api/remote.mux 升级需 Cookie 认证,丢弃即 401 连不上),仅覆盖 Host/Origin 为回环目标、剥离 hop-by-hop 与 WS 握手专有头;上游被 targetHost 强制约束为回环,凭据只发往本机回环上游(不承诺跨进程隔离)。压缩炸弹面:桥接浏览器段 permessage-deflate 解压存在放大点(LAN 内恶意客户端高压缩比帧 → 代理进程 解压)——在「LAN 信任」威胁模型内可接受(与 injectToken 同一信任边界)
的链路,不触碰 dsh web 的响应生成;不新增可达数据面,仅增加少量 CPU 开销 (可经 httpCompressEnabled: false 关闭)。health/标记路由的 loopback 围栏 对直连回环 web 的请求生效;经本插件转发的请求按设计视为受信(见凭据面)。 注意:health 响应携带的诊断元数据——configDir 绝对路径与压缩协商计数—— 会随转发原样到达局域网设备,对其可见
dsh web 的浏览器会话认证(launch token
局域网设备拿不到实时 token。本插件经官方 connection 服务的公开 API authenticatedUrl() 动态读取当前 token,仅在铸造入口(GET /、无会话 cookie) 自动补上:LAN 设备零操作进入。安全取舍与缓解:
获得完整 dsh 控制权(bash 直通宿主机)。仅在可信家庭/办公内网开启; 不可信网段务必关闭(设置卡片开关)。
trusted_networks认证 provider、qBittorrent WebUI 「Bypass authentication for clients」)默认 需显式配置;本插件按家用固定内网场景默认开启,以「启动横幅警示行 + 设置 卡片常驻警示 + 本节说明」作缓解。
在关闭后仍可直接进入;需立即收回访问时清空 dsh credentials 存储。
401 死锁(Max-Age 内浏览器不删 cookie、又拿不到新 token);转发层在检测到 上游 401 后自动带 token 重放一次,上游直接重铸 cookie,设备无感恢复。
http://:3081/ 发起的跨站GET 可被白铸 cookie,但读不到响应(CORS opaque)、后续请求因 SameSite=Strict 不携带 cookie、POST /api 被 sec-fetch-site 围栏拒绝—— 链条闭合;token 与 cookie 均不出现在浏览器地址栏/历史。
GET / 且无 token 参数的请求;WebSocket、非根路径、已带 token 的请求、provider 不可用时全部原样透传(行为与未开启一致)。 自建口令页(信任收窄为「知道口令」)为后续演进方向。
经官方 webServer 注入钩子向非回环页面声明 ownsHost,恢复 Host 设置持久化面与 「打开配置文件」动作。它伪造的是页面侧拓扑事实,不是服务端授权变化:/api 围栏、 launch token 与会话 cookie 认证保持不变;兼容开启后,LAN 页面与回环页面在界面上不再可区分。
dsh-lan-proxy,keyed row 为 @wingsky-1/dsh-lan-proxy#dsh-lan-proxy, 官方 settings namespace 使用 dsh-lan-proxy。
plugins.row.config 渲染,仅在 Host 服务 canonical settings 条目时注册。compat-off 或上游契约漂移时,非回环页面可能无法进入配置行。
/api/dsh-lan-proxy/health 显示宿主侧开关;页面加载时若兼容未生效或契约漂移,浏览器控制台给出独立告警,不依赖配置页。
dsh-lan-proxy.ownsHostCompat(宿主使用 settings.yaml 时,以「打开配置文件」显示的 路径为准),或执行 ssh -L 3080:127.0.0.1:3080 后访问 http://127.0.0.1:3080/。两者都是恢复旁路,不是常规配置路径。
安装即开端口:本插件会在0.0.0.0:3081(HTTP)与0.0.0.0:3443(HTTPS)监听,局域网内所有设备都可访问你的 dsh web。不需要时请卸载(见后文卸载)。
dsh plugin --profile web add @wingsky-1/dsh-lan-proxy安装 / 卸载 / 更新后都需重启一次 dsh web(bundle 层只在启动时组合)生效。在可信局域网设备打开 https://:3443/(或 http://:3081/)。自签名证书首次访问需手动「继续访问」,详见 HTTPS 支持。
在宿主机检查健康端点:
curl -s http://127.0.0.1:3081/api/dsh-lan-proxy/health键 · 默认 · 说明 enabled · true · 总开关(关闭后转发器停止监听) host · 0.0.0.0 · 监听地址 port · 3081 · HTTP 监听端口 httpsPort · 3443 · HTTPS 监听端口 targetHost · 127.0.0.1 · 回环上游主机(仅允许回环地址) targetPort · 自动 · 上游端口(默认取 web 服务器实际绑定端口) httpsEnabled · true · 是否并存 HTTPS tlsCertFile / tlsKeyFile · 无 · 自定义证书(mkcert 等) tlsCaCertFile · 无 · 自建 LAN CA 公钥(PEM,仅读) printBanner · true · 启动时是否在终端打印监听横幅(LAN 访问地址等) wsBridgeEnabled · true · 桥接总开关;关闭会失去保活与压缩。 wsCompressEnabled · true · 是否对命中 wsCompressPaths 的 WebSocket 做压缩桥接(仅控制压缩,不影响桥接保活) wsCompressPaths · /api/remote.mux · 参与 WebSocket 压缩的路径白名单(清空 = 桥接不压缩,保活不受影响) wsDeflatePolicy · {browser:true, uaDeny:[iPhone…]} · 浏览器压缩策略与 UA 排除规则。 httpCompressEnabled · true · 转发层 gzip/Brotli 压缩开关。 httpCompressLevel · 1 · gzip 与 Brotli 共用的 0..3 档位。 injectToken · true · LAN 免 token 直入,默认开;见安全模型。 ownsHostCompat · false · 伪造页面侧宿主事实位,默认关;见安全模型。
配置页入口:Plugin Manager → dsh-lan-proxy → Configure(保存即热更新)。
非回环 LAN 地址默认不提供持久化设置面,Configure 按钮按 DSH 安全策略隐藏;请从127.0.0.1:3080/127.0.0.1:3081或 SSH 回环隧道管理。只有在可信 LAN、明确接受共享控制面风险时,才开启ownsHostCompat恢复远程设置入口。
dsh-lan-proxy,落盘位置由宿主统一管理。组合层 cordis.patch.yml 的 config 作为 base 层生效; 热更新由官方 settings/document-updated 事件驱动,无需重启。
DSH 官方 importer 会按同名 section 直接导入 dsh-lan-proxy;本插件不再运行第二套 namespace migration。settings.yaml.imported 仅为已消费文档的审计副本,不应整体复制。
旧 config.json 迁移
~/.dsh/lan-proxy/config.json。升级后首次启动会自动把存量 config.json 一次性迁移进官方存储:原文件原子改名保留为 config.json.migrated.bak 备份;若写入官方存储失败会自动还原改名、下次 启动重试;若进程在写入完成前退出(中断),下次启动检测到备份残留会自动 从备份重放写入并以日志提示。确认运行正常后可手动删除该备份。 此后手改 config.json 不再生效。
wsBridgeEnabledWebSocket 桥接总开关(issue #552):true = 所有 WS 升级一律走「终结 + 桥接」(保活基座:ws 库自动代答上游 Ping + 半开探活);false = TCP 字节透传(显式放弃保活与压缩,移动端切后台可能被上游心跳判死而频繁断连重连,见「WebSocket 压缩」节)
wsDeflatePolicyWS 压缩协商策略:browser 为 false 全局关压缩;uaDeny 为不协商压缩的 UA 片段列表(iOS Safari 默认拦截,见「WebSocket 压缩」节)
httpCompressEnabledHTTP 响应压缩总开关(转发层对可压缩响应协商 gzip/Brotli;Brotli 生效条件见「HTTP 响应压缩」节,合并自 dsh-gzip)
httpCompressLevel压缩档位预设 0..3:0 默认 / 1 低(gzip 1 / br 2,最快)· 2 中(gzip 5 / br 5,均衡)/ 3 高(gzip 9 / br 9,最高压缩比),gzip 与 Brotli 两侧参数同时按下发;旧配置整数 4..9 自动迁移为 3
injectToken