前言¶
DeepSeek Harness(DSH)在浏览器侧通常会持有核心签发的 dsh-auth-* 自包含 bearer cookie。一旦 cookie 泄露,在过期前调用方仍可能直接访问 API,且难以在服务端「立刻作废」浏览器里的凭据。若要把 Web 界面放到 Nginx 后面、又希望多一层登录校验,常见做法是再套一层网关或改核心认证流程,运维和安全边界都要自己捋清楚。
下面介绍社区插件 dsh-totp-proxy(维护者 realjhen123):它既是 DSH/Cordis 插件,也是面向 DSH 上游的反向代理,内置 TOTP 与固定 token 登录,浏览器只持有可吊销的 dsg_session,原始 dsh-auth-* 留在代理服务端。
这是什么¶
dsh-totp-proxy 定位是:独立 DSH/Cordis 插件 + 反向代理;零额外运行时依赖,要求 Node.js 22+(实现仅使用 node:http / node:https)。当前 package 版本为 0.2.0,许可证 MIT。
典型链路如下(摘自 README 架构说明):
浏览器 --dsg_session--> Nginx :80/:443 --> dsh-totp-proxy 127.0.0.1:3090 --dsh-auth cookie--> DSH 127.0.0.1:3080
代理自行校验 TOTP / 固定 token,读取 DSH 的 browser-session 签名密钥,签发 DSH 核心认可的 cookie;每个 HTTP 请求与 WebSocket upgrade 均经代理校验,删除服务端 session 即可立即吊销。
核心功能¶
认证方式¶
通过 authMode(或环境变量 DSH_TOTP_PROXY_AUTH_MODE)控制:
authMode |
行为 |
|---|---|
totp |
只接受 6 位验证码 |
token |
只接受固定 token |
both |
两者任一(默认) |
凭据在首次运行时自动生成,保存在 ~/.dsh/dsh-totp-proxy/:
totp.json— Base32 TOTP secrettoken.json— 固定访问 token
连续失败达到上限(默认 10 次)会按 IP 锁定(默认 60 秒)。TOTP 可配合 Apple Passwords、1Password 等常见验证器使用。
与 DSH 原生 cookie 的差异¶
DSH 核心的 dsh-auth-* 是自包含 bearer cookie;浏览器若已持有,即使再弹验证码也可能在过期前直接调 API。本代理把原始 cookie 留在服务端,浏览器只拿到随机 session(默认 cookie 名 dsg_session),从架构上缩小浏览器可见的高权限凭据面。
安全边界(作者说明)¶
能做到: 浏览器看不到 dsh-auth-*;删除服务端 session 立即吊销;所有 API / WebSocket 统一校验。
仍须注意: dsg_session 仍是 bearer credential,被窃取后可在 TTL 内重放;需 HTTPS、HttpOnly、SameSite=Strict 与较短 TTL;session 在内存中,代理重启后需重新登录。
项目 NOTICE 还强调:面向公网环境的设计思路,但不要把本方案直接部署在真实公网;若使用插件,应确保 Nginx(或任意反代)只能代理到 3090,3080 不得对外可达。
安装与启用¶
作为 DSH 插件¶
README 给出的示例命令(路径需换成你本机克隆或下载后的插件目录):
dsh plugin --profile web add /home/coder/project/dsh-totp-proxy -w
可用 cordis.patch.yml 覆盖配置,例如:
- id: dsh-totp-proxy
config:
host: 127.0.0.1
port: 3090
target: http://127.0.0.1:3080
cookieSecure: true
authMode: both
独立运行¶
不通过 Cordis 挂载时,可直接启动入口脚本:
node totp-proxy.mjs
本地校验¶
npm run check # 语法检查 + node --test
典型用法与配置¶
常用环境变量¶
完整默认值见仓库 src/server.mjs 中的 DEFAULTS。常用项如下:
| 变量 | 默认 | 说明 |
|---|---|---|
DSH_TOTP_PROXY_HOST |
127.0.0.1 |
监听地址 |
DSH_TOTP_PROXY_PORT |
3090 |
监听端口 |
DSH_TOTP_PROXY_TARGET |
http://127.0.0.1:3080 |
DSH 上游 |
DSH_TOTP_PROXY_AUTH_MODE |
both |
totp / token / both |
DSH_TOTP_PROXY_TOTP_SECRET |
空 | 直接指定 Base32 secret |
DSH_TOTP_PROXY_TOKEN |
空 | 直接指定固定 token |
DSH_TOTP_PROXY_SESSION_TTL_MS |
1800000 |
代理 session TTL |
DSH_TOTP_PROXY_COOKIE_NAME |
dsg_session |
浏览器 cookie 名 |
DSH_TOTP_PROXY_COOKIE_SECURE |
false |
HTTPS 后置 1 |
DSH_TOTP_PROXY_BROWSER_SESSION_SECRET |
空 | DSH cookie 签名密钥 |
DSH_TOTP_PROXY_CREDENTIALS_FILE |
~/.dsh/.credentials.yaml |
读取签名密钥的文件 |
DSH_TOTP_PROXY_UPSTREAM_SESSION_PATH |
/api |
上游会话校验路径 |
设置 DSH_TOTP_PROXY_COOKIE_SECURE=1 时必须配合 HTTPS;DSH 的 3080 与代理的 3090 都不应直接暴露到公网。
无 GUI 环境下绑定 TOTP¶
配置页要求经本机访问。若 DSH 跑在没有图形界面的虚拟机里,首次或忘记 TOTP 时,README 建议用 SSH 本地端口转发:
ssh dsh@dsh -NL 3080:127.0.0.1:3080
随后在本地浏览器打开 127.0.0.1:3080 查看二维码并完成 TOTP 绑定。
修改代理相关配置时:
ssh dsh@dsh -NL 3090:127.0.0.1:3090
在 127.0.0.1:3090 管理 dsh-totp-proxy 的配置。
部署要点¶
- 只对外暴露 Nginx(
:80/:443),反代到127.0.0.1:3090,并转发Upgrade/Connection以支持 WebSocket。 - DSH 仅监听
127.0.0.1:3080。 - 生产环境设置
DSH_TOTP_PROXY_COOKIE_SECURE=1。 ~/.dsh/.credentials.yaml(含client-connection/browser-session密钥)权限保持0600。
适用场景与注意¶
适合: 已在内网或受控边界内用 Nginx 暴露 DSH Web,希望增加 TOTP 或固定 token 一层、且需要服务端可吊销的浏览器会话,而不是把完整 dsh-auth-* 交给浏览器。
安装前: 插件随当前 DSH 进程权限运行;安装前应自行审阅源码与 MIT 许可证。DSH 生态强调「一切皆插件」;社区目录 SkillHub 插件页 为独立站点,与 DeepSeek / 幻方无官方从属关系。
经过上面的步骤,你可以在反代之后统一做 TOTP/token 校验,并用 dsg_session 控制吊销面;细节与更新以仓库 README 为准。
- 目录页:https://www.skillhub.cn/plugins/realjhen123/dsh-totp-proxy
- GitHub:https://github.com/realjhen123/dsh-totp-proxy