HomoLand
dsh-remote-access-patch
No description
- Stars
- 0
- Language
- Shell
- Created
- Aug 15, 2026
- Updated
- Aug 15, 2026
Introduction
dsh-remote-access-patch
让 dsh(DeepSeek Harness)的「配置平面」从仅限本机 loopback 放行为可在受信域名下远程读写的一键脚本。
一个可开源的、幂等、可回滚的补丁工具,把 docs/cluster/dsh-external-access-deployment.md 第 6 节的两处手工补丁自动化。
它解决什么问题
dsh 0.1.0-rc.6 把配置平面限制在本机,有后端 + 前端两层栅栏,即使配了 --trusted-host 域名,远程浏览器仍:
- 后端:15 个「特权方法」(
settings.*、agentPreset.*、credentials.*、host.pickDirectory、llm.discoverModels等)被isTrustedApiRequest(request, [])空信任列表拒绝 →/api/settings.describe返回 403; - 前端:
connection.isLoopback因location.hostname非回环而为false,settings scope 落到"memory"(status="unavailable")→ 插件配置卡片不渲染。
本脚本放行这两处,让远程登录用户可以正常读写设置与插件配置。
⚠️ 安全前提(必须先读)
dsh 源码注释明说:trustedHosts 是 DNS-rebinding 栅栏,不是认证层;配置平面在「真正的认证层」出现之前保持 loopback-only。
因此只有在 dsh 之前已前置了真正的认证层(如 Authelia forwardAuth + two_factor/TOTP,或等效的 SSO/OIDC 网关)时,本补丁才是安全的:
- 所有远程请求必须先通过登录 + 二次验证才能到达 dsh;
- dsh 进程仍应只绑
127.0.0.1,经收口(如 socat)暴露给内网,不直接暴露公网。
没有认证层就不要用本脚本把 dsh 暴露到公网。
前置条件
- Linux,
bash4+,python3(用于精确替换),grep; npm root -g可解析(或手动传--dsh-root);- 修改 dsh 安装目录需要 root(文件属 root)。
用法
./dsh-remote-access-patch.sh [status|apply|rollback] [选项]
| 命令 | 作用 |
|---|---|
status(默认) | 只读查看两处补丁状态与备份情况 |
apply | 应用两处补丁(幂等;首次自动备份 .orig-bak) |
rollback | 从 .orig-bak 恢复原始文件 |
| 选项 | 说明 |
|---|---|
--dsh-root DIR | dsh 模块根目录(默认 $(npm root -g)/@deepseek-ai/dsh/node_modules/@deepseek-ai) |
--service NAME | 配合 --restart 重启的 systemd 服务(默认 dsh.service) |
--restart | 完成后 systemctl restart 该服务(需 root) |
环境变量 DSH_ROOT 等价于 --dsh-root。
典型流程
# 1) 看现状
sudo ./dsh-remote-access-patch.sh status
# 2) 打补丁并重启
sudo ./dsh-remote-access-patch.sh apply --restart
# 3) 浏览器强制刷新(Ctrl+Shift+R)→ 设置 → 插件,确认卡片已渲染且可编辑
# 4) 需要回滚时
sudo ./dsh-remote-access-patch.sh rollback --restart
补丁内容对照
| # | 文件 | 改动 |
|---|---|---|
| 1(后端) | dsh-client-connection/lib/index.js | isTrustedApiRequest(request, []) → isTrustedApiRequest(request, trustedHosts)(仅 privileged 方法闸门那一行;第 237 行 Typert interceptor 的 loopback 判定不动) |
| 2(前端) | dsh-client-ui-settings/lib/client.js | SettingsScopeController(..., connection.isLoopback ? "host" : "memory") → SettingsScopeController(..., "host") |
设计要点
- 幂等:重复
apply不会二次修改,输出[SKIP]。 - 升级安全:按唯一锚串定位(不依赖行号),dsh 重装覆盖补丁后重新
apply即可;升级后.orig-bak会被刷新为当前版本的原始内容,保证rollback回到当前版本未打补丁的状态。 - 精准:锚串带
PRIVILEGED_METHODS.has(method)前缀,避免误伤同文件第 237 行另一处isTrustedApiRequest(request, []);出现多匹配时拒绝执行并报错。 - 可回滚:
apply前先cp -a到.orig-bak,rollback一键恢复。 - 只读安全:
status不写任何文件。
升级 dsh 后
npm install -g @deepseek-ai/dsh 会覆盖两个补丁文件。升级后重新执行:
sudo ./dsh-remote-access-patch.sh status # 应看到 [TODO] 未打补丁
sudo ./dsh-remote-access-patch.sh apply --restart
开发与测试
本地自测(不依赖真实 dsh 安装,用 test/fixture/ 最小夹具跑完整循环):
make check # bash -n 语法检查
make test # 功能自测(status/apply/rollback/幂等/逐字节回滚)
make lint # shellcheck(需先安装 shellcheck)
CI:.github/workflows/ci.yml 在每次 push / PR 上执行 bash -n、shellcheck、bash test/run.sh。
文件
dsh-remote-access-patch/
├── dsh-remote-access-patch.sh # 主脚本
├── Makefile # check / test / lint
├── test/
│ ├── run.sh # 功能自测
│ └── fixture/ # 最小夹具(含 lookalike 行)
├── .github/workflows/ci.yml # GitHub Actions CI
├── README.md # 本说明
└── LICENSE # MIT