dsh-gateway-plugin:给 DeepSeek Harness Web 加一道访问密码网关

前言

把 dsh web 部署到服务器、想从浏览器远程使用时,会先撞上一个问题:这个 Web 应用本身没有密码验证,谁拿到地址都能打开。harness 本体按官方要求保持 127.0.0.1 回环绑定(禁止绑 0.0.0.0),常见的做法是在前面自己架一层带认证的反向代理,但这意味着额外维护一份代理配置。

下面介绍的 dsh-gateway-plugin 把这件事做成了 DSH 插件:装进 profile 后,它会开一个自己的网关端口作为唯一对外入口,网关端口上除登录/首次设置页外,不存在任何未认证可达的内容面。

这是什么

dsh-gateway-plugin 由 laoin114514 维护,MIT 许可证,定位是 DeepSeek Harness Web 的访问密码网关插件。

它以插件形式实现了一道「密码反代」:浏览器访问网关端口,未认证的请求被拦下;通过认证的请求才反向代理到 harness,并由网关改写 Host/Origin,放行 harness 内部的信任围栏。整个过程不需要动 harness 本体。

核心能力

1、绝对门禁。网关监听端口上只有 /gateway/login(GET 页面 + POST 登录/设密)未认证可达,没有其他例外:未认证的页面与静态资源 302 到登录页,/api 返回 401,WebSocket 升级直接拒绝。

2、首次设置密码。部署还没有密码时,登录页呈现设置表单,首个访问者设置成功后立即获得会话;之后所有人用该密码登录。

3、修改密码。在设置的独立「安全」页完成(当前密码 + 新密码 ×2);修改成功后所有已登录会话立即失效(签名密钥轮换)。

4、防爆破。密码比对先做 SHA-256,再用 timingSafeEqual 做恒定时间比较;登录失败按来源地址限流,默认连续 5 次失败冷却 30 秒。

5、无状态会话。会话是 HMAC-SHA256 签名的 cookie(HttpOnlySameSite=Lax),签名密钥每次进程启动随机生成——重启即全员重新登录,属有意的 fail-closed 行为。

6、两种认证方式。支持会话 cookie,或请求头 Authorization: Bearer <密码>

7、开箱即用。构建产物(lib/)已随仓库提交,git 安装后无需运行构建脚本、无需放行 build 权限。

安装与启用

前提是 dsh CLI 已安装(或使用源码检出)。执行:

dsh plugin --profile web add github:laoin114514/dsh-gateway

为防止仓库后续推送悄悄改变安装到的代码,推荐固定到具体 commit:

dsh plugin --profile web add github:laoin114514/dsh-gateway#<commit-sha>

安装后启动 dsh web,日志中会打印网关地址:

dsh-gateway: http://127.0.0.1:3088 (gateway, password required) -> harness http://127.0.0.1:3080

经过上面的步骤,注意此后要打开的是网关地址,而不是 harness 地址。首次访问时登录页会引导设置访问密码,之后每次访问输入该密码即可。

典型用法

暴露到网络

默认网关只绑 127.0.0.1。需要从其他机器访问时,在 $DSH_HOME/profiles/web/cordis.patch.yml 中为 dsh-gateway 行覆盖 gatewayHost

- id: dsh-gateway
  config:
    gatewayHost: '0.0.0.0'

harness 本体仍保持回环绑定(官方禁止 0.0.0.0),网关是唯一对外入口。

可配置项

网关在 cordis.patch.ymldsh-gateway 行上提供以下配置:

  • gatewayHostgatewayPort:网关监听地址与端口;
  • sessionTtlHours:会话有效期;
  • minKeyLength:密码最短长度;
  • maxLoginFailuresloginCooldownSeconds:登录失败限流的阈值与冷却时长(默认连续 5 次失败冷却 30 秒);
  • accessKey:初始密码,留空即进入首次设置模式。

安装失败排查

如果 dsh plugin addERR_PNPM_ENOENT 一类错误(常见于之前失败安装留下的半装目录),先清理再重装:

dsh plugin --profile web remove dsh-gateway-plugin
# 或手动删除半装目录:
rm -rf "$DSH_HOME/profiles/web/node_modules/dsh-gateway-plugin"
dsh plugin --profile web add github:laoin114514/dsh-gateway

源码检出下的本地开发

需要与仓库源码联动时,先检出源码,再在仓库根执行:

pnpm dsh web --patch <dsh-gateway>/cordis.dev.yml --no-open --port 3082

注意:以 --patch overlay 方式启动时,浏览器侧的「安全」设置页不会加载——只有 profile 行才能被客户端模块系统发现。

适用场景与注意

适合的场景:把 dsh web 跑在服务器或内网中、希望通过浏览器访问、又不想让端口裸奔的部署。

使用前注意以下几点:

  • 插件不提供 TLS。公网或跨网段传输需在网关前再放一个终结 TLS 的反向代理,或把网络限制在内网。
  • 密码以明文存于用户设置文件(设置命名空间 dsh-gateway,字段 accessKey,声明为 role('secret'),任何 wire 响应都不会携带它),请按机密文件的权限管理该文件。
  • 会话签名密钥每次进程启动随机生成,重启后所有会话失效、需重新登录,这是有意的 fail-closed 行为。
  • 默认网关只绑 127.0.0.1;harness 本体应保持回环绑定(官方禁止 0.0.0.0)。
  • 与安装任何 DSH 插件一样,插件以当前 dsh 进程的权限运行,安装前建议先查看源码与许可证(本项目为 MIT)。

小结

dsh-gateway-plugin 用一条 profile 安装命令的代价,换来了网关端口上「没有未认证内容面」的保证:密码的首次设置、修改、登录限流、会话失效策略都是现成的,harness 本体可以继续安全地留在回环地址后面。

插件收录在社区插件目录(独立站点,与 DeepSeek / 幻方无官方从属关系):https://www.skillhub.cn/plugins/laoin114514/dsh-gateway ,源码仓库:https://github.com/laoin114514/dsh-gateway 。

羽毛球分组比赛记分
小程序二维码

欢迎使用《羽毛球分组比赛记分》微信小程序

小夜