前言¶
把 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(HttpOnly、SameSite=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.yml 的 dsh-gateway 行上提供以下配置:
gatewayHost、gatewayPort:网关监听地址与端口;sessionTtlHours:会话有效期;minKeyLength:密码最短长度;maxLoginFailures、loginCooldownSeconds:登录失败限流的阈值与冷却时长(默认连续 5 次失败冷却 30 秒);accessKey:初始密码,留空即进入首次设置模式。
安装失败排查¶
如果 dsh plugin add 报 ERR_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 。