让反向代理已认证的请求免登录直连 DSH
29.9/100
综合分
0
GitHub 星标
—
npm 周下载
—/5
用户评分
数据截至 2026/9/26 · 周下载取自 npm 全网(含 CI / 镜像),非本站安装数;综合分由星标、活跃度与兼容性检查合成。
安装命令 · 需先装 dsh CLI 引擎
dsh plugin --profile web add lukepoo101/dsh-trusted-proxy-auth该包不可直接 npm 安装,改从 GitHub 源安装(明细见下方安装检查)
状态速览
判定依据:实装验证 · 静态安装检查 · 自动扫描 · 仓库维护状态信任档位:已验证
是什么
dsh 原生插件 · browser
安全吗
本站尚未对该插件做风险分级
暂未覆盖,不等同于无风险
还在维护吗
更新放缓:最近一次提交在 40 天前
档位由哪些信号合成
本站实装验证(真实安装 L4 覆盖全站;L5 为运行时冒烟或实机截图,覆盖范围小于 L4) · 验证所用 dsh 版本 · 静态安装检查 · 风险分级 · 仓库维护状态。 下方各区块是它的证据明细。
社区实装还没有人打卡 · 装过的第一个就是你
安全扫描自动 · 静态分析源码v2.7.0🟢 扫描:未发现敏感能力尚无人工评估展开查看扫描说明与证据 ↓
安全扫描自动 · 静态分析源码
v2.7.0静态扫描未发现敏感能力:最多只发网络请求、读取自身元数据或只读文件,未发现执行命令、文件写入或敏感信息读取。
扫描于 2026/11/4(0 天前) · 范围 入口闭包 + 发布文件清单 · 来源 GitHub 仓库
静态扫描只反映源码中出现的调用,不构成安全背书;人工评估与自动扫描相互独立、互不覆盖。
给这个插件打分还没有人投票↓
用户评分
还没有人投票,来当第一个
功能亮点
- 信任反向代理认证
- 免登录直连
- 保留原生认证兜底
DeepSeek Harness 插件,信任反向代理(Traefik + Keycloak OIDC)已完成的认证,同时保留 DSH 原生浏览器认证作为兜底。
README
由 DeepSeek 最新模型翻译生成dsh-trusted-proxy-auth
一个小型的、仅限主机的 DeepSeek Harness (DSH)插件,为前置可信反向代理的部署添加第二条独立认证路径——例如 Traefik → Keycloak OIDC → DSH。
当反向代理已经对调用方完成认证后,它会在请求头中注入一个私有共享密钥。DSH 随后将该请求视为已认证。当该请求头缺失或错误时,DSH 原生的浏览器启动令牌/cookie 认证会一如既往地运行,因此直接回环/SSH 访问仍然可用。
该插件不会替换 DSH 的传输层、修补 DSH 安装目录内的任何文件,也不实现 OIDC/JWT 逻辑。它只是一个认证边界适配器,仅此而已。
外部浏览器 │ ▼ Traefik ───────────► Keycloak OIDC │ (身份、登录、角色、会话) │ │ 注入: X-DSH-Proxy-Auth: ▼ DSH ─────────────► trusted-proxy-auth │ 401 原生浏览器认证 + 有效密钥 ──► 放行 │ 403 Host/Origin 防护 ──► 仍为 403 ▼ 原生 DSH 传输层,保持不变
SSH 隧道 / 直接访问 │ (无 X-DSH-Proxy-Auth 请求头) ▼ DSH ─────────────► 原生 ?token=…
展开完整文档(README 剩余 1 节)
dsh-trusted-proxy-auth
一个小型的、仅限主机的 DeepSeek Harness (DSH)插件,为前置可信反向代理的部署添加第二条独立认证路径——例如 Traefik → Keycloak OIDC → DSH。
当反向代理已经对调用方完成认证后,它会在请求头中注入一个私有共享密钥。DSH 随后将该请求视为已认证。当该请求头缺失或错误时,DSH 原生的浏览器启动令牌/cookie 认证会一如既往地运行,因此直接回环/SSH 访问仍然可用。
该插件不会替换 DSH 的传输层、修补 DSH 安装目录内的任何文件,也不实现 OIDC/JWT 逻辑。它只是一个认证边界适配器,仅此而已。
外部浏览器 │ ▼ Traefik ───────────► Keycloak OIDC │ (身份、登录、角色、会话) │ │ 注入: X-DSH-Proxy-Auth: ▼ DSH ─────────────► trusted-proxy-auth │ 401 原生浏览器认证 + 有效密钥 ──► 放行 │ 403 Host/Origin 防护 ──► 仍为 403 ▼ 原生 DSH 传输层,保持不变
SSH 隧道 / 直接访问 │ (无 X-DSH-Proxy-Auth 请求头) ▼ DSH ─────────────► 原生 ?token=… / cookie 流程
状态
- 已在 Node v24.21.0 上针对 DSH 0.1.5-rc.2 测试(Node 20 和 22 由 CI 覆盖)。
- 86 个单元测试和 37 项实时 DSH 集成检查通过。参见 docs/VALIDATION.md。
- 启动时的不变量会在每次启动时重新验证 DSH 的 403/401 语义,因此语义变化不会悄悄地将该插件变成绕过手段。
- 为经代理认证的请求向 index HTML 注入一个由服务器验证的 __DSH_TRANSPORT__.ownsHost = true 引导脚本,从而在跨源场景下实现完整的主机设置持久化(模型目录、插件配置)。
- 将经代理认证的请求规范化为回环地址,以用于 webServer.match 和 webServer.handle 路由,使具有严格回环检查的第三方插件(例如 dshmarket)能够无缝工作,同时严格防止跨源 CSRF 攻击。
- 无运行时依赖——仅使用 node:crypto。
- 无构建步骤;纯 ESM。
安装
生成一个密钥(96 个十六进制字符绰绰有余):
openssl rand -hex 48
将其添加到 DSH 服务已读取的环境变量中(例如 /etc/dsh/env,root:dsh,权限 0640):
SECRET="$(openssl rand -hex 48)"
printf 'DSH_PROXY_AUTH_SECRET=%s\n' "$SECRET" | sudo tee -a /etc/dsh/env >/dev/null
sudo chown root:dsh /etc/dsh/env
sudo chmod 0640 /etc/dsh/env
将插件包安装到 Web 配置文件中并重启:
从 Git 检出目录
dsh plugin --profile web add /path/to/dsh-trusted-proxy-auth
或直接从本仓库安装,固定到已发布的标签
dsh plugin --profile web add git+https://github.com/lukepoo101/dsh-trusted-proxy-auth.git#v0.2.3
对于认证边界插件,使用确切的提交哈希同样可以接受
dsh plugin --profile web add git+https://github.com/lukepoo101/dsh-trusted-proxy-auth.git#
sudo systemctl restart deepseek-harness
请固定标签或提交哈希,而不要跟随 main:该插件位于认证边界上,因此安装的版本应当是你已审查过的版本。升级时请有意地提升版本号。
验证组合后的配置文件中包含该插件以及Connection 传输层:
dsh web --dump-config | grep -E -A1 "connection|trusted-proxy-auth"
- id: connection
name: '@deepseek-ai/dsh-client-connection'
...
- id: trusted-proxy-auth
name: dsh-trusted-proxy-auth
还必须告知插件它所服务的公共权威地址。将最终的公共主机名添加到 DSH 启动参数中:
dsh web --trusted-host dsh.example.com
配置
| 设置项 | 位置 | 说明 |
| DSH_PROXY_AUTH_SECRET | 环境变量 | 必需。 至少 32 字节的可打印 ASCII 字符,且不能包含逗号。切勿将其写入 YAML。 |
| X-DSH-Proxy-Auth | 请求头 | 仅由反向代理注入。绝不发送到浏览器。 |
没有插件配置键。密钥缺失、为空、过短或格式错误都会导致插件激活时大声失败,从而使配置文件启动失败——服务器绝不会以半认证状态启动。openssl rand -hex 48(十六进制)和 openssl rand -base64 48 都满足可接受的字符集;排除逗号和空白字符正是使重复/拼接请求头的保证明确无歧义的原因。
行为
requestRejection()(由 /api 和 WebSocket 多路复用器使用):
| 上游结果 | 密钥 | 结果 |
| 403(Host/Origin/DNS 重绑定防护) | 有效 | 403 |
| 403 | 缺失/错误 | 403 |
| 401(原生浏览器认证) | 有效 | 允许 |
| 401 | 缺失/错误 | 401 |
| undefined(原生认证已通过) | 任意 | 允许 |
authorizeIndex()(前端 / 路由):
| 密钥 | Host 防护 | 结果 |
| 缺失/错误 | — | 委托给原始原生流程 |
| 有效 | 403 | 403 forbidden,响应结束 |
| 有效 | 401 或 undefined | 提供 index,并注入 ownsHost: true 引导 |
该插件绝不被允许将上游的 403 转为成功,因此即使密钥正确,DNS 重绑定和跨站保护仍然有效。
设置持久化与 ownsHost 引导
DSH 的客户端设置服务通过以下方式解析持久化策略:
persistence = ctx.remote.$host.isLoopback ? 'host' : 'memory'
当通过反向代理访问时(例如 https://dsh.example.com),window.location.hostname 是非回环地址,导致 DSH 切换到内存持久化模式,使 Models 和 Plugins 为空,并显示“设置不可用在此浏览器中"。
为了在不信任任意客户端主机名的情况下安全地解决此问题, dsh-trusted-proxy-auth 挂接到 DSH 支持的 Web 服务器扩展接缝(webServer.tapIndex 和 webserver/index-inject 事件)以注入:
globalThis.__DSH_TRANSPORT__=Object.assign(globalThis.__DSH_TRANSPORT__||{},{ownsHost:true});
到 中,在渲染 Web 外壳时。DSH 的连接包会评估 transport?.ownsHost === true,设置 isLoopback = true 并为经过代理认证的操作员会话激活 'host' 持久化。Node 的 ServerResponse 管道保持完全未修改,确保标准的 HTTP 分块流式传输和标头不会被截断。
第三方插件路由兼容性与回环规范化
若干 DSH 插件(最显著的是 dshmarket@1.65.1,它为内置的插件市场提供支持)使用严格的回环检查来保护其 HTTP 变更路由(/dsh-market/discovery-compatibility、/dsh-market/update、 /dsh-market/install):
const sameOrigin = (req) => isLoopback(req.headers.host) && (!req.headers.origin || req.headers.origin === http://${req.headers.host})
当 DSH 由反向代理前置时,传入的请求携带公共域名(例如 Host: dsh.example.com)。
在反向代理(例如通过 Nginx 或 Envoy)盲目重写 Origin 会全面剥离 CSRF 防御,并有可能将状态变更端点暴露给恶意网站。
为了安全且通用地解决此问题:
1. dsh-trusted-proxy-auth 通过 ctx.webServer.match(以 webServer.handle 作为回退)拦截路由分发。
2. 对于携带有效 X-DSH-Proxy-Auth 标头的请求,它针对真实的入站标头调用 DSH 未装饰的 connection.requestRejection(req)。
3. 如果请求未通过 Host/Origin 防护(例如来自 https://evil.example 的攻击者触发跨源 CSRF 请求,或不受信任的 Host 标头),则立即以 HTTP 403 Forbidden 拒绝,并结束响应,而不调用下游处理程序或规范化标头。
4. 对于已验证的代理请求,该插件:
- 在 X-Forwarded-Host 和 X-Forwarded-Proto 中保留原始公共权威。
- 将 req.headers.host 规范化为 127.0.0.1:。
- 将 req.headers.origin(如果存在)规范化为 http://127.0.0.1:。
5. 下游插件路由处理程序针对规范化后的标头运行其回环检查,以 200 OK 成功。
反向代理契约
Traefik(或任何等效代理)必须:
1. 要求 Keycloak OIDC 认证成功。
2. 移除或覆盖任何入站的 X-DSH-Proxy-Auth 值。
3. 仅在经过认证的 DSH 路由上添加私有的 X-DSH-Proxy-Auth 值。
4. 在普通 HTTP 请求以及 WebSocket 升级上转发该标头。
5. 保留原始公共 Host。
6. 保留浏览器 Origin 行为。
在路由器上设置该标头可同时满足 (2) 和 (3),因为
Traefik 会覆盖传入的值:
Traefik 动态配置(示意) http: middlewares: dsh-proxy-auth: headers: customRequestHeaders: X-DSH-Proxy-Auth: '' routers: dsh: rule: 'Host(dsh.example.com)'
entryPoints: [websecure]
middlewares: [dsh-proxy-auth]
service: dsh
services:
dsh:
loadBalancer:
servers:
- url: 'http://10.0.20.103:3081'
DSH 服务必须在 --trusted-host 中包含最终的公开域名:
--trusted-host dsh.example.com
代理→DSH 这一跳以明文携带密钥。 上面的示例转发到 http://10.0.20.103:3081;任何能够被动监听该路径的实体都可以恢复 X-DSH-Proxy-Auth 并重放它。防火墙可以阻止不需要的连接,但无法防止嗅探,因此请执行以下操作之一:
- 将该跳保持在隔离的可信网段或加密覆盖网络(WireGuard、VXLAN+IPsec)上,并将其记录为明确的部署假设;或
- 在代理与 DSH 之间终止 TLS——最好是 mTLS。
网络限制仍然是必需的。 共享密钥是纵深防御,而不是防火墙的替代品:任何能够直接访问 DSH 端口并且知道密钥的人都可以绕过原生身份验证。请对 VM/LAN 端口设置防火墙,使只有 Kubernetes/Traefik 网络可以访问它。
运维
轮换密钥。 生成新值,更新 /etc/dsh/env 和 Traefik 中间件,然后重启 DSH。变更期间正在进行的请求会回退到原生身份验证。
紧急/管理员访问。 dsh web 打印的原生身份验证 URL(http://127.0.0.1:3080/?token=…)不受影响。通过 SSH 隧道,你始终可以使用 DSH 自己的浏览器会话登录,独立于 Traefik。
升级 DSH。 插件在每次启动时都会验证运行时接口:
sudo npm install -g @deepseek-ai/dsh@latest
sudo systemctl restart deepseek-harness
systemctl status deepseek-harness
journalctl -u deepseek-harness -n 100
如果未来的 DSH 重命名或移除 requestRejection / authorizeIndex,或更改其 403/401 语义,插件会拒绝激活,配置文件将无法启动,而不是静默丢弃身份验证。
卸载。
dsh plugin --profile web remove dsh-trusted-proxy-auth
sudo systemctl restart deepseek-harness
安全属性
- 整个断言就是“调用方知道一个只有代理和 DSH 共享的私有密钥”。任何 X-Forwarded-User、电子邮件、用户名、角色或 JWT 声明都绝不会被视为身份验证。
- 比较使用 crypto.timingSafeEqual() 对 UTF-8 字节进行。
- 格式错误、重复、数组值、组合或非字符串的标头都会导致身份验证失败。
- 密钥、标头值、cookie 和启动令牌绝不会被记录。
- 密钥必须是可打印的 ASCII,且不包含逗号或空白,因此一个重复或拼接后的 HTTP 头值永远无法与之相等。
- 每次激活都会探测原始的 requestRejection,并且除非 403 仍然表示 Host/Origin 信任围栏、401 仍然表示“原生浏览器会话缺失”,否则拒绝启动。若 DSH 升级改变了这些语义,配置文件会失败,而不是悄然变成绕过。
- 该插件仅装饰单个活跃的 ctx.connection 实例;它从不触碰 HostConnectionService.prototype,也从不写入 DSH 安装目录内部。
- 激活是故障关闭且事务性的:错误配置会阻止配置文件启动,任何部分装饰(包括验证失败的写入,或注册失败的清理器)都会被回滚,意外的运行时异常会保留原生认证或使请求失败——绝不会静默返回 true。
完整威胁模型请参见 SECURITY.md。
测试
npm test # 50 unit tests, node:test, no dependencies
npm run test:integration # 35 live checks against a real DSH server
npm run test:integration 会创建一个临时 DSH_HOME,从随附的 web 模板派生一个私有配置文件,安装此检出,在空闲回环端口上启动真实的 Harness Web 服务器,并测试 HTTP 索引路由、/api、/api/remote.mux WebSocket 升级、原生令牌/cookie 登录、故障关闭启动以及日志卫生。它从不触碰现有的 Harness home 或正在运行的服务器。使用 KEEP_TMP=1 可保留临时 home 以供检查。
CI 有两条轨道:在 Node 20/22/24 上运行单元测试套件,以及在每次 push 和 pull request 时针对固定版本 0.1.5-rc.2 运行真实 DSH 集成测试套件,同时有一个定时任务针对 @deepseek-ai/dsh@latest 运行相同的集成测试套件,作为上游漂移的早期预警信号。
运行时兼容性
DSH 0.1.5-rc.2 向插件提供的是 ctx.connection 的 Cordis 可追踪代理,而不是原始服务实例。通过该代理读取方法时,每次访问都会返回一个新的影子方法代理,因此引用相等性检查并不稳定。因此,该插件通过 Object.getOwnPropertyDescriptor 捕获并恢复方法,从而触及真实实例:
- ctx.connection 是一个代理;Object.isExtensible(ctx.connection) 为 true。
- requestRejection、authorizeIndex 和 authenticatedUrl 是继承的、可写的、不可枚举的原型方法(own=false)。
- 通过代理赋值会在原始实例上创建自有属性;通过代理执行 delete 会移除该属性并再次暴露原型方法。
清理采用比较并交换,并会解开它发现的任何包装器,因此重复或重叠激活不会堆叠包装器,实例会精确恢复到其原始形态(当方法为继承时,自有属性会被删除)。包装器标记是一个已注册(Symbol.for)的 symbol,因此两代模块一次性加载后仍能相互识别。原始探测输出见 docs/VALIDATION.md。
形状并非契约的全部,因此激活时还会对照原始方法断言 DSH 的语义:未经认证的环回请求必须返回 401,不受信任的 Host 必须返回 403,跨源/跨站请求必须返回 403。如果未来的 DSH 在应用信任围栏之前就进行了认证——以至于不受信任的 Host 返回 401——那么提升该 401 将不再安全,插件会拒绝启动。
非目标
本插件有意不包含以下任何内容:
- Keycloak 库、JWT 验证、OAuth/OIDC 发现
- 用户管理、登录页面、会话、TOTP、角色、权限映射
- 浏览器端代码
- 检查 Keycloak 访问令牌,或将其传入 DSH
- 向浏览器暴露共享密钥
Traefik 和 Keycloak 负责这些事项。本插件仅是一个认证边界适配器。
许可证
MIT预览分享卡片长什么样 ↓
分享 · DeepSeek Harness Hub
lukepoo101/dsh-trusted-proxy-auth
让反向代理已认证的请求免登录直连 DSH
相关插件 · 浏览器
智能体插件框架deepseek-ai/deepseek-harness
DeepSeek Harnessdsh是由 DeepSeek AI 开发的开源 agent harness智能体框架。
★ 270,422已汉化DSH
71.9
多设备 Agent 看板YaoApp/yao
✨ 所有 Agent 和工作区集中管理,覆盖你的每一台设备。任务看板追踪进度,桌面端、移动端、浏览器、API…
★ 8,147已汉化DSH
71.2
可扩展侧边栏工作台omdsh-dev/DSH-better-sidebar
DSH 的双工作台:原生右侧栏 + 自绘底部面板,并把 ctx.betterSidebar 服务开放给所有插件
★ 4,761已汉化DSH
71.1
浏览器自动化桥Tencent/BrowserSkill
你的 Agent。你的浏览器。连接,就能协作。
★ 9,967已汉化DSH
71
AI 小说创作工作台EthanYoQ/AI-Novel-Writer
AI 小说作家 / AI Novel Writer
★ 1,591已汉化DSH
70.7
智能体浏览器引擎platonai/Browser4
DeepSeek Harness 集成
★ 1,175已汉化DSH
70.4
这是你的仓库?认领条目