zzy2210
dsh-web-gate
DeepSeek Harness (dsh) Web 密钥门禁 / Access gate for dsh Web GUI — 替换出厂 webserver 行,HTTP/WebSocket/SPA 全部先过密钥:登录页 + HMAC Cookie + Bearer Token + 防爆破;host/port/key 环境变量或行内可配;0.0.0.0 无密钥拒绝启动(安全锁). Login page, HMAC cookie, bearer token, lockout; env/row config; refuses 0.0.0.0 without key.
- Stars
- 0
- Language
- JavaScript
- Created
- Aug 14, 2026
- Updated
- Aug 14, 2026
Introduction
y1n-web-gate
dsh web profile 的网页密钥门禁(本地包)。把"需要密钥才能进入界面"落在真正的
HTTP 边界上: 所有 HTTP 路由(/api、插件包路由、HMR)、WebSocket upgrade
(/api/events.mux、/api/events.host)以及 SPA fallback(页面与静态资源),
在任何业务逻辑之前先过鉴权。
安装
-
在 web profile 目录(
~/.dsh/profiles/web)安装本包:npm install --save github:zzy2210/dsh-web-gate或手写
package.jsondependencies:"y1n-web-gate": "github:zzy2210/dsh-web-gate"(包名以包内package.json的name为准,即y1n-web-gate)。 -
把本仓库
install.patch.yml里的两个条目合并进~/.dsh/profiles/web/cordis.patch.yml(禁用出厂webserver行 + 插入守卫行)。 -
按下方「配置」设置密钥,重启
dsh web。
机制
cordis.patch.yml禁用出厂webserver行;本包继承@deepseek-ai/dsh-host-webserver的WebServer,以同一个webServer服务键提供实例 —— 所有路由消费者(frontend-static、client-connection、 client-modules、HMR 等)透明拿到守卫实例。register/registerUpgrade/registerFallback在原型上覆盖为 "先鉴权再转发",覆盖随对象一同诞生、早于服务对外可见,不存在激活顺序竞态。- 密钥不落盘:HMAC 会话 cookie 的签名密钥由门禁密钥本身派生,不引入第二个秘密。
配置
监听 IP、端口、密钥三者均可通过环境变量或配置文件(cordis.patch.yml
行内)配置,优先级:环境变量 > 行内配置。DSH 故意拒绝 .env 文件里的
DSH_* 变量,环境变量用 systemd Environment= 或 shell export 传入:
| 变量 | 含义 |
|---|---|
DSH_WEB_GATE_KEY | 访问密钥(任意非空字符串,越随机越好) |
DSH_WEB_GATE_HOST | 监听 IPv4 字面量(localhost/::1 归一为 127.0.0.1) |
DSH_WEB_GATE_PORT | 监听端口:0-65535(0 = 系统分配) |
DSH_WEB_GATE_MODE | auto(默认)/ off(整体关闭门禁与安全锁,显式接受风险) |
export DSH_WEB_GATE_KEY='<随机长密钥>'
dsh web --host 10.126.126.9 --port 3080 --trusted-host 10.126.126.9:3080
dsh@0.1.0-rc.6打印的dsh web: http://127.0.0.1:3080是固定的规范 本地 URL,不是实际套接字状态。指定地址部署时以ss -ltnp显示的监听地址为准。
也可在 cordis.patch.yml 行内配置(不推荐把密钥写进文件):
config:
host: !!js ctx.webStartup.host ?? '127.0.0.1' # 监听 IP
port: !!js ctx.webStartup.port ?? 3080 # 监听端口
# key: 'change-me'
# sessionTtlSeconds: 604800 # cookie 有效期,默认 7 天
# maxFailedAttempts: 10 # 同 IP 连续失败阈值,默认 10
# lockoutSeconds: 900 # 触发后锁定秒数,默认 15 分钟
行为
- 配置了密钥: 一切请求都要凭证(含回环访问)。
- 浏览器: 未登录导航 →
/gate/login登录页 → 提交密钥 → 303 回首页; 会话 cookie(HttpOnly + SameSite=Lax)默认 7 天有效,重启后仍有效 (签名由密钥派生);登出:/gate/logout;健康检查:/gate/status。 - 脚本:
Authorization: Bearer <key>,例如curl -H 'Authorization: Bearer <key>' http://host:3080/api/...。 /api未鉴权一律401 {"error":"unauthorized"},不重定向。
- 浏览器: 未登录导航 →
- 未配置密钥: 门禁关闭,回环直通;安全锁在绑定任意非
127.0.0.0/8地址时拒绝启动(fail loud),防止裸奔网络。绑定指定网卡地址需用DSH_WEB_GATE_HOST=10.126.126.9或行内host: '10.126.126.9'—— 此时必须 配置密钥。浏览器通过该地址访问时,同时给 CLI 传入--trusted-host 10.126.126.9:3080。 - 防爆破: 同 IP 连续失败
maxFailedAttempts次锁定lockoutSeconds秒, 两次尝试最小间隔 250ms。
启用 / 回滚
cordis.patch.yml中已包含webserver禁用 +y1n-web-gate插入两个条目。- 重启
dsh web生效。 - 回滚: 注释/删除这两个条目并重启;或临时
DSH_WEB_GATE_MODE=off。 - 忘记密钥: 重启时换一个新的
DSH_WEB_GATE_KEY,全部旧 cookie 立即失效。
已知限制(v1)
- 不支持反向代理场景的
X-Forwarded-For(防爆破按直连 socket 地址计数); 经反代部署时请在反代层加 basic auth / IP 限制。 - cookie 未带
Secure(默认 HTTP 部署);经 TLS 反代时可在反代层处理。