Skip to content

dsh-lan-compat

Verified

dsh-lan-compat · v0.1.1 · MIT

在 DSH 0.2.1+ 中保持 0.0.0.0 局域网监听与固定端口同 @linxin666/dsh-remote-web-ui 的兼容。

Install

dsh plugin add dsh-lan-compat

Confirm the layer applied with dsh --profile default --dump-config — see the install guide.

Source

Published to npm without a public repository. Inspect the package contents before installing.

Tags

Readme

dsh-lan-compat

在 DSH 0.2.1+ 中恢复 0.0.0.0 / :: 局域网监听与固定端口,保持同 @linxin666/dsh-remote-web-ui 的 lanBind 托管块兼容。

解决什么问题

升级到 DSH 0.2.1+ 后,开启 @linxin666/dsh-remote-web-ui 的局域网访问(lanBind: true)或配置 webserver 监听 0.0.0.0 时,会遇到四处连环不兼容:

  1. 启动阶段直接报错退出: @deepseek-ai/dsh-host-webserver 在 WebServer.Config.dict.host 的 Schema 校验中用 isWildcardAddress 显式拦截 0.0.0.0 与 :::

    Error: webserver: host "0.0.0.0" is an unspecified (wildcard) address, which is not supported:
    binding every interface would expose remote code execution to the network;
    bind one concrete IPv4 or IPv6 address of a local interface instead
    

    由于 webserver 在 requiredStartupEntryIds 中,校验失败会导致整个 DSH Web / Desktop Host 启动失败退出。

  2. 内部通告 Origin 变成 http://0.0.0.0:<port>: 放行 0.0.0.0 后,WebServer.prototype.getOrigin() 默认直接把 this.config.host 拼进 URL,导致 dsh-web-app 打印的启动 URL、自动打开的浏览器地址以及注入子进程的 DSH_WEB_URL 全部变成 http://0.0.0.0:<port>。 同时又不能把 this.config.host 改写成 127.0.0.1:因为 @linxin666/dsh-remote-web-ui 依赖 ctx.webServer.host === '0.0.0.0' 来识别局域网绑定状态并生成配对二维码的 lanBases / lanUrls。

  3. 桌面端默认启动参数把 cordis.patch.yml 的托管块冲成 127.0.0.1:0: DSH Desktop 的 @deepseek-ai/dsh-desktop-host 启动 desktop profile 时固定传入:

    args: ["--no-open", "--host", "127.0.0.1", "--port", "0"]
    

    web-startup 将其解析为 webStartup = { host: '127.0.0.1', port: 0, ... }。@linxin666/dsh-remote-web-ui 在启动后执行 applyLanBindWork 时,看到 startup.host === '127.0.0.1' 与 startup.port === 0,会误以为是用户从命令行显式覆盖了绑定地址与端口,进而把 cordis.patch.yml 里的 lan-bind block 改写为 host: '127.0.0.1', port: 0,废掉局域网监听与固定端口(如 19387)。

  4. dsh-web-app 移除 webRuntime.trustedHosts 导致局域网 Origin 被判为 untrusted origin: DSH 0.2.0 在 0.0.0.0 监听下会自动将本机所有非内部 IPv4 网卡地址写入 webRuntime.trustedHosts 并传给 connection.trustedHosts;DSH 0.2.1+ 删掉了 webRuntime.trustedHosts,改为仅读取 ctx.webStartup.trustedHosts(默认为空数组 [])。依赖 ctx.connection.trustedHosts 做同源校验的插件(如 dshmarket 的 sameOrigin)在局域网浏览器访问 <LAN_IP>:19387 发起更新/安装 POST 请求时,会直接返回 403 {"error":"untrusted origin"}。

怎么解决

本插件在 Host 侧针对上述四处做最小原地修补:

  1. 放行 0.0.0.0 / :: 配置校验: 在模块导入期同步加载 @deepseek-ai/dsh-host-webserver(此时 webserver fiber 仍在等待 webStartup 注入,尚未执行 _resolveConfig),原地包装 WebServer.Config.dict.host.callback:当值为 '0.0.0.0' 或 '::' 时直接放行,其余值仍走原校验函数。

  2. 通配监听下将 getOrigin() 映射回 127.0.0.1: 包装 WebServer.prototype.getOrigin:当 this.config.host 为 '0.0.0.0' 或 '::' 时返回 ${this.protocol}//127.0.0.1:${String(this.listenedPort)}(未绑定端口时仍保持原异常),同时保留 webServer.host === '0.0.0.0' 供 remote-web-ui 读取。

  3. 清除桌面端默认占位的 webStartup 参数: 在 apply(ctx) 中注入 webStartup,当且仅当检测到 startup.host === '127.0.0.1' && startup.port === 0 时删除 startup.host 与 startup.port,使 remote-web-ui 的 desiredBindHost / desiredBindPort 按 lanBind 开关与实际监听端口保持 0.0.0.0:19387。

  4. 通配监听下同步本机局域网 IPv4 到 connection.trustedHosts: 在 apply(ctx) 中注入 connection,当 webServer.host 为 '0.0.0.0' 或 '::' 通配地址时,通过动态 getter 将 os.networkInterfaces() 的非内部 IPv4 地址并入 connection.trustedHosts(同时同步到 webStartup.trustedHosts),恢复 DSH 0.2.0 的局域网受信任主机列表,且支持运行期 DHCP 换 IP 与插件热重载即时生效。

影响范围

维度 限定
目标模块 @deepseek-ai/dsh-host-webserver(WebServer.Config.dict.host.callback 与 WebServer.prototype.getOrigin)及 webStartup 服务对象
放行地址 仅 '0.0.0.0' 与 '::';其它非法文本或 0.0.0.1 等仍按上游原逻辑拒绝
getOrigin() 改写 仅在 config.host 为 '0.0.0.0' 或 '::' 时返回 127.0.0.1:<port>;绑定具体网卡 IP 时保持原行为
webStartup 清理 仅在 host === '127.0.0.1' && port === 0 同时成立时清除;用户在 CLI 显式指定的 --port 19387 或 --host 192.168.x.x 原样保留

失败姿态(重要)

DSH 升级后若 @deepseek-ai/dsh-host-webserver 内部结构发生变化,插件在启动自检(selfCheck)时会通过 console.error 输出诊断:

[dsh-lan-compat] 自检失败:@deepseek-ai/dsh-host-webserver 结构已变更(hostSchema=..., getOrigin=...)。
[dsh-lan-compat]   DSH 升级后 WebServer.Config.dict.host 或 WebServer.prototype.getOrigin 可能已改动,
[dsh-lan-compat]   请更新 lib/index.js。

自检失败只报错、不抛异常——未启用 0.0.0.0 时 DSH 照常启动。诊断走 console.error 而非 ctx.logger:实测 ctx.logger 的 info/warn/error 在默认日志级别下均不可见。

安装

从 npm 安装(标准路径):

dsh plugin --profile desktop add dsh-lan-compat

首次安装后需要重启 DSH。

更新:

dsh plugin --profile desktop update dsh-lan-compat

⚠️ 如果 profile 里原本是 link: 指向本地仓库(开发时的装法),必须先 remove 再 add —— 直接 add 会认为「已是最新」并静默保留 link::

dsh plugin --profile desktop remove dsh-lan-compat
dsh plugin --profile desktop add dsh-lan-compat

成功的标志是 profile 的 package.json 里那一行变成 "^0.1.0" 这样的版本范围,而不再是 link:…。

验证

npm run check          # node --check lib/index.js 语法检查
npm test               # 单测(含真实 app.asar 结构守卫)
npm run test:isolation # 隔离脚本的静态守卫
npm run verify         # 上面三步串联(prepublishOnly 自动执行)

起隔离实例验收

./tools/dev-instance.sh verify        # 建一次性 DSH home + 装本仓库 + 跑真实 0.0.0.0 启动验收
./tools/dev-instance.sh verify npm    # 装 npm 上的已发布副本再验收(发布后必跑)
./tools/dev-instance.sh web           # 常驻起一个 web 实例做人工检查(端口 23387)
./tools/dev-instance.sh reset         # 连隔离 home 一起删

verify 在仓库内的隔离 home(.dsh-dev)里用标准安装路径装上本插件,写入 0.0.0.0:23387 的 webserver 托管块,并以 --no-open --host 127.0.0.1 --port 0 启动完成真机验收。

交付时实测过的对照(隔离 home 内):

检查项 结果
移出插件后启动(反向对照) 启动失败:webserver: host "0.0.0.0" is an unspecified (wildcard) address
标准路径装回插件后启动 正常就绪,监听固定端口 23387
运行态 webStartup 默认占位(127.0.0.1:0) host 与 port 字段已被清除
启动日志通告 URL dsh web: http://127.0.0.1:23387/?token=...(不含 http://0.0.0.0:)
本机回环访问 127.0.0.1:23387 正常响应(401)
局域网网卡访问 <LAN_IP>:23387 正常响应(401)
主力实例 127.0.0.1:19387 全程不受影响