# 局域网访问 WebUI > 让同一网络下的电脑浏览器直接打开**手机里的原生 WebUI**——不是另做一个界面,而是把手机上的那份 > dsh WebUI 原样送到电脑屏幕上。 ## 1. 为什么上游不直接支持 dsh 引擎只监听 `127.0.0.1`,这是上游的安全设计(源码明确拒绝绑定 `0.0.0.0`: "would expose remote code execution to the network")。即使强行改成监听所有网卡,浏览器访问 `http://192.168.x.x` 也会连撞四道门: | # | 阻塞点 | 后果 | |---|---|---| | ① | `crypto.randomUUID` 仅安全上下文可用 | 页面初始化直接抛错 | | ② | 前端 `isLoopbackHostname(location.hostname)` 判假 | 连接被标记为非回环,设置持久化降级为内存 | | ③ | `/api` 的 Origin / Host 同源检查 | 请求被拒 | | ④ | WebSocket 升级需要被转发 | 对话流推不下来(界面不更新) | ## 2. 方案:应用层反向代理(端口 3090) app 内置一个 node 反向代理(`assets/tools/lan-web-proxy.mjs`),只监听独立端口 **3090**, 转发到本机 `127.0.0.1:3080`,并在**内存里**修补响应: - 注入 `crypto.randomUUID` polyfill; - 把 `isLoopbackHostname(...)` 的调用点改写为真值; - 把上游 `Host` / `Origin` 规范化为 `127.0.0.1:3080`; - 转发 WebSocket 升级(对话流实时性靠它); - 处理 `SameSite=Strict` cookie 与 chunked 编码。 **原则**:不修改磁盘上的任何引擎文件;补丁只存在于代理返回的响应体里;代理异常只影响自己, 绝不抛到引擎。 ## 3. 使用步骤 1. 手机与电脑连同一网络(同一 WiFi,或手机开热点让电脑连上); 2. 手机打开 **设置 → 扩展 → 局域网访问 WebUI**,阅读提示后确认开启; 3. 弹出提示框显示: - **6 位验证码**(大号字,点一下复制;每次开启都重新随机生成); - 访问地址 `http://<手机IP>:3090`(也可点击复制); 4. 电脑浏览器打开该地址,输入验证码即可。 > 🔐 验证码只在开启时显示**一次**,之后不再展示(设置页行内也不保留)。 > 忘记了就关掉再开一次,会生成新的。 ## 4. 常驻提醒与关闭 局域网一旦开启就会持续监听,很容易忘记关。所以开启成功后,通知栏会出现一条**常驻通知**: - 标题:「局域网 WebUI 已开启」; - 正文:`http://<手机IP>:3090 · 点「关闭」可停止`; - 动作按钮:**关闭**。 关闭链路(任意一个入口都有效): | 入口 | 行为 | |---|---| | 通知里的「关闭」 | 清偏好 → 停代理进程 → 撤通知 | | 设置页开关 | 同上 | | 通知栏「退出」引擎 | 引擎退出时一并停掉代理与通知 | 代理进程停止采用「**同 uid 直接 kill**」:app 对自己 fork 的 node 进程天然有权限, 不需要 Shizuku 或 root —— 因此**普通模式**下也能真正关掉(旧版本在普通模式下会残留进程)。 ## 5. 安全说明 - 只在你信任的网络里开启;不要做公网端口映射; - 代理后面是一个拥有完整文件与命令权限的 Agent —— 验证码就是唯一门槛,不要截图外传; - 不使用时点通知里的「关闭」,或直接退出引擎(会连带停止代理); - 代理**不监听** 3080(引擎 WebUI)和 3083(能力桥),只占用 3090。 ## 6. 故障排查 | 现象 | 排查 | |---|---| | 电脑打不开地址 | 确认手机与电脑同网段;`ping <手机IP>`;确认 3090 在监听(代理启动约需 2 秒) | | 提示验证码错误 | 验证码区分大小写;关掉再开会生成新码;确认浏览器没有缓存旧的 cookie | | 页面空白 | 检查 WebView/浏览器版本(Chrome 85+);看代理日志 `$DSH_HOME/lan-proxy.log` | | 关闭后电脑还能访问 | 旧版本残留进程;升级到含「同 uid 直杀」的版本后重试 | | 通知栏没有常驻提醒 | 检查应用通知权限(Android 13+);没有权限时代理仍工作,但不会提醒 | ## 7. 相关文件 | 文件 | 作用 | |---|---| | `app/src/main/assets/tools/lan-web-proxy.mjs` | node 反向代理(部署到 `dsh-home/tools/`) | | `app/src/main/java/app/dsh/mobile/engine/LanWebProxy.kt` | Kotlin 侧启停、鉴权、常驻通知、进程清理 | | `app/src/main/java/app/dsh/mobile/LanWebOffReceiver.kt` | 通知「关闭」按钮的广播接收器 | | `app/src/main/java/app/dsh/mobile/LanAccessDialog.kt` | 显示验证码与地址的提示框 |