🎁 福利专区全网大模型免费应用 + 新用户福利 + 注册活动入口,低成本玩转 AI

零信任网关 TiantianFlow/dsh-one-gateway

DeepSeek Harness
TiantianFlow69 天前有提交已提供中文文档扫描:含敏感能力

把 DSH Web 分享给你指定的人,而不是整个网络。

37.6/100
综合分
14
GitHub 星标
—
npm 周下载
—/5
用户评分

数据截至 2026/9/18 · 周下载取自 npm 全网(含 CI / 镜像),非本站安装数;综合分由星标、活跃度与兼容性检查合成。

自动兼容检查有告警:未发布到 npm registry,仅可从源码安装。
安装命令 · 需先装 dsh CLI 引擎
dsh plugin --profile web add TiantianFlow/dsh-one-gateway
该包不可直接 npm 安装,改从 GitHub 源安装(明细见下方安装检查)

状态速览

判定依据:实装验证 · 静态安装检查 · 自动扫描 · 仓库维护状态
信任档位:仅索引
是什么
dsh 原生插件 · security
装得上吗
静态安装检查有提示项,装前建议看一眼 README
L4 · 真实安装等级说明 →
安全吗
本站尚未对该插件做风险分级
暂未覆盖,不等同于无风险
还在维护吗
更新放缓:最近一次提交在 69 天前
档位由哪些信号合成

本站实装验证(真实安装 L4 覆盖全站;L5 为运行时冒烟或实机截图,覆盖范围小于 L4) · 验证所用 dsh 版本 · 静态安装检查 · 风险分级 · 仓库维护状态。 下方各区块是它的证据明细。

验证判据与等级说明 →
社区实装还没有人打卡 · 装过的第一个就是你
安装兼容性检查⚠ 装前注意

未发布到 npm registry,仅可从源码安装

展开查看检查明细 ↓

以下结论由程序自动检查 npm 包、engines 声明与入口文件得出,未做人工实机验证——能装不等于用着没问题。

✗npm 包dsh-one-gateway(未发布到 npm,仅可源码安装)
✓Node 引擎要求 >=20.0.0 · 基线 Node 22.19 满足
✓dsh CLI 依赖未声明 dsh 版本约束
✓入口文件main/exports/bin 已声明

验证方式:npm registry 存在性 + package.json 静态校验 · 最后检查 2026/10/31 04:48:35

安全扫描自动 · 静态分析源码
v2.7.0
🔵 扫描:含敏感能力尚无人工评估
展开查看扫描说明与证据 ↓

静态扫描发现插件具备触达本地系统的能力:执行外部命令、读写/删除本地文件、读取剪贴板或密钥类环境变量(至少其一)。这是能力清单,不是危险判定——具体能力项与证据见下方,安装前请自行判断是否需要。

可执行外部命令读写/删除本地文件
查看扫描证据(共 12 处,展示前 12 条)
  • 执行外部命令固定命令
    src/setup/cli.mjs:80
    const result = spawnSync('tailscale', argv, { encoding: 'utf8', maxBuffer: 512 * 1024, shell: false })
  • 读取本地文件
    src/auth/credential-store.mjs:68
    const info = await stat(path)
  • 读取本地文件
    src/auth/credential-store.mjs:83
    const raw = await readFile(path, 'utf8')
  • 写入本地文件
    src/auth/credential-store.mjs:88
    await mkdir(dirname(path), { recursive: true, mode: 0o700 })
  • 写入本地文件
    src/auth/credential-store.mjs:100
    await writeFile(temporary, payload, { encoding: 'utf8', mode: ALLOWED_MODE })
  • 写入本地文件
    src/auth/credential-store.mjs:101
    await chmod(temporary, ALLOWED_MODE)
  • 写入本地文件
    src/auth/credential-store.mjs:102
    await rename(temporary, path)
  • 写入本地文件
    src/auth/credential-store.mjs:103
    await chmod(path, ALLOWED_MODE)
  • 执行外部命令来自配置/变量
    src/setup/detect.mjs:8
    const result = spawnSync(name, ['--version'], { encoding: 'utf8', timeout: 5_000, shell: false })
  • 读取本地文件
    src/core/tls.mjs:18
    info = await stat(path)
  • 读取本地文件
    src/core/tls.mjs:60
    certPem = await readFile(tls.certPath)
  • 读取本地文件
    src/core/tls.mjs:65
    keyPem = await readFile(tls.keyPath)
扫描于 2026/11/3(0 天前) · 范围 入口闭包 + 发布文件清单 · 来源 GitHub 仓库

静态扫描只反映源码中出现的调用,不构成安全背书;人工评估与自动扫描相互独立、互不覆盖。

给这个插件打分还没有人投票↓
用户评分
还没有人投票,来当第一个

功能亮点

  • 指定人员访问
  • 身份优先入口
  • 仅限本机回环

DSH 私有网关:面向 DeepSeek Harness 的回环、身份优先入口

README

由 DeepSeek 最新模型翻译生成
DSH One Gateway English · 简体中文 把 DSH Web 分享给你指定的人,而不是整个网络。 DeepSeek Harness(DSH)插件,在 DSH Web 前面架一道私有、零信任的网关。一份允许清单。密码不由用户自选。连着同一个 Wi-Fi、同一个 tailnet 或同一个 mesh,绝不足以进门。 快速上手 你需要一个能正常运行的本地 DSH Web 配置档,以及 Node.js 20+(通常由 DSH 提供)。装完插件什么都不会发生,直到你跑 setup。不会有任何东西暴露出去。 安装 dsh plugin --profile web add github:TiantianFlow/dsh-one-gateway 配置 dsh plugin --profile web exec dsh-gateway -- setup setup 会打开菜单,预览一份方案,然后等你确认。它拒绝公开或匿名的默认值。用 Tailscale.com 的运维人员会被引导到带身份识别的 Tailscale Serve。 接着重启你原本就在跑的 DSH Web 进程,再以允许清单里的主体身份打开配置好的 HTTPS 源。3088 端口本身从局域网和服务商网络都不可达。 完整命令是 dsh-one-gateway;dsh-gateway 是更短的别名。
展开完整文档(README 剩余 1 节)
DSH One Gateway

English · 简体中文

把 DSH Web 分享给你指定的人,而不是整个网络。

DeepSeek Harness(DSH)插件,在 DSH Web 前面架一道私有、零信任的网关。一份允许清单。密码不由用户自选。连着同一个 Wi-Fi、同一个 tailnet 或同一个 mesh,绝不足以进门。

快速上手

你需要一个能正常运行的本地 DSH Web 配置档,以及 Node.js 20+(通常由 DSH 提供)。装完插件什么都不会发生,直到你跑 setup。不会有任何东西暴露出去。

安装

dsh plugin --profile web add github:TiantianFlow/dsh-one-gateway

配置

dsh plugin --profile web exec dsh-gateway -- setup

setup 会打开菜单,预览一份方案,然后等你确认。它拒绝公开或匿名的默认值。用 Tailscale.com 的运维人员会被引导到带身份识别的 Tailscale Serve。

接着重启你原本就在跑的 DSH Web 进程,再以允许清单里的主体身份打开配置好的 HTTPS 源。3088 端口本身从局域网和服务商网络都不可达。

完整命令是 dsh-one-gateway;dsh-gateway 是更短的别名。Cloudflare Access、Headscale、本地检出、无人值守参数都在详细配置里。

你能得到什么

DSH 前面一份精确的主体允许清单,一个只监听回环的 HTTP/WebSocket 代理,还有一条引导命令,它会预览方案,并拒绝公开或匿名的默认值。

网关和 DSH 都留在回环上。Tailscale Serve、带 Cloudflare Access 的 Cloudflare Tunnel,或者经 Tailscale TCP Serve 的 Headscale,只是私有入口。加入那个私有网络绝不等于授权。每个请求都必须解析出一个明确、且在允许清单里的主体,之后才会转发给 DSH。这就是给零信任 homelab 用的自托管访问控制:能连上不等于有权限。

Allowlisted browser ─ HTTPS ─> provider ingress (Tailscale Serve, Cloudflare Access,
│ or Headscale TCP Serve)
└─ loopback gateway ─> local DSH
127.0.0.1:3088 127.0.0.1:3080

调用方通过 Tailscale Serve、Cloudflare Access 认证,或者在 Headscale 上,通过私有 TCP Serve 前面一个生成的网关凭据认证。

有什么不一样

其他 DSH 网关可能绑定到非 loopback 地址,或者给 DSH 内部打补丁,让某个网关在升级后仍保持穷尽覆盖,或者在 DSH 前面跑反向代理。这些设计也能覆盖 /api 和 WebSocket;区别不在于谁覆盖的面更大。这个插件是另一种契约:DSH 本身永远不离开 loopback。

1. 私网成员身份永远不等于授权。 绑定 0.0.0.0,或者把 RFC1918 当成允许名单,都不在范围内。监听器始终留在 loopback。跟别人连同一个 Wi-Fi、tailnet 或 mesh,并不能让你进来。
2. DSH 源站 fail-closed。 DSH 留在 loopback;网关是它前面唯一的监听器。DSH 升级不可能悄悄加一条路由,就变得能从主机外访问——根本不存在需要保持穷尽的网关路由表,因为 DSH 从一开始就无法从主机外访问。全覆盖网关漏掉一条路由,就是一次静默绕过;这座桥漏掉一条路由,只是那一条被代理的路径断掉。它不会暴露 DSH。
3. 不打 DSH 核心或客户端库补丁。 有些网关靠给 DSH 的 HTTP 和 upgrade 入口打补丁来保持穷尽覆盖,然后每次升级后再重新打一遍——因为上游改动可能悄悄让补丁失效。这个网关是外部进程。DSH 自己的代码从不修改。
4. 对 Tailscale Serve 和 Cloudflare Access,身份来自服务商——不是登录页、密码或共享 token。 密码表单、共享 token、会话 cookie 门禁,是一大片认证面,也是 bug 的常见来源。已发布的这两种模式,用的是 Serve 注入的 Tailscale-User-Login,或者本地验证的 Cloudflare Access JWT。我们查允许名单。我们不要求你自己编一个密码。
gateway-credential 是更小、专门为没有原生身份的传输方式打造的登录方式:按主体生成的凭据(不是用户自选的密码)、只存验证器、有界的 HttpOnly/Secure/SameSite=Strict 会话、可单独吊销、限流但不会永久锁定。跟典型的用户自选密码或共享密码相比,它在可猜性、存储泄露和吊销上更强;它不是「无密码」,也不是宣称比所有密码或 passkey 都优越。Headscale TCP Serve 就是使用这种模式的已发布传输方式。对任何没有原生身份的纯传输服务商,契约都是一座产品自有的桥,从私有 overlay 通到未改动的 loopback 网关,用 gateway-credential 认证——绝不伪造身份头。
5. 一个插件,一条引导命令,一份允许名单。 Tailscale Serve、Cloudflare Tunnel with Access 和 Headscale TCP Serve 共用一个 loopback 网关,而不是每个服务商一套定制的安装流程。新服务商只是另一个适配器,不是另一个产品。

详细安装步骤

在终端里,省略 --provider 就会从菜单里选——那就是这条命令在 Getting started 中。检测本地可执行文件只是提示,当恰好找到一个服务商时,它作为默认值——不是配置检查。传 --provider 可跳过菜单。非交互式安装仍会在恰好检测到一个服务商可执行文件时自动选择,否则必须传 --provider。当活动节点在 Headscale 上时,会列出 Headscale TCP Serve。

从本地检出安装,而不是从 GitHub:

dsh plugin --profile web add -w /path/to/dsh-one-gateway

Tailscale Serve:

dsh plugin --profile web exec dsh-gateway -- setup --provider tailscale-serve

Cloudflare Access(Access 由你自己配置;网关只在本地校验 token)。你必须已经有一个 Access 应用,且只转发到 127.0.0.1:3088:

dsh plugin --profile web exec dsh-gateway -- setup --provider cloudflare-access \
--external-origin 'https://dsh.example.invalid' \
--team-origin 'https://team.example.invalid' \
--application-audience 'replace-with-access-application-audience' \
--trusted-principal 'email:operator@example.invalid'

在 TTY 中,省略的 Cloudflare 值会按以下顺序交互式收集:现有 Access origin、team origin、application audience、可信邮箱。无人值守的 --yes 仍要求提供全部四个参数。安装过程绝不会创建隧道、DNS 记录或 Access 应用。

Headscale TCP Serve(私有可达性,外加生成的网关凭据;证书由你提供)。在 Tailscale.com 上安装时,不会把它作为同等的菜单选项提供:

dsh plugin --profile web exec dsh-gateway -- setup --provider headscale-tcp-serve \
--tls-cert /path/to/dsh-one-gateway/cert.pem \
--tls-key /path/to/dsh-one-gateway/key.pem \
--credential-store /path/to/dsh-one-gateway/credentials.json \
--trusted-principal operator-1

TCP Serve 不终止 HTTPS,也不证明身份。网关在 127.0.0.1:3088 上用运维方提供的证书终止 TLS。客户端必须信任该证书;这一步不会生成私有 CA。确认后,安装过程会签发一个凭据,打印一次原始密钥,绝不把它写入配置档。--print 不签发任何东西。

确认后会写入一条启用的配置档条目。安装过程绝不猜测、杀死或重启你的 supervisor。请重启你自己拥有的 DSH Web 进程。

用 --print 预览而不写入。在 TTY 中,--print 仍可能提示你选择服务商并补全缺失的值,但绝不写入配置档、服务商资源或凭据。非交互式 --yes 要求显式提供每一个安全敏感的值。--yes 只跳过最后的写入确认;它不会凭空编造服务商或 Cloudflare 值。

支持的服务商

| 服务商 | 认证模式 | 证明什么身份 | 安装过程做什么 |
| Tailscale Serve | trusted-header — Serve 注入登录头 | Serve 覆盖调用方提供的值之后,注入的精确 Tailscale-User-Login。不是「tailnet 上的任何人」。 | 可以为你创建一条缺失的私有 Serve 路由(routeManagement: ensure),或者只检查路由是否已存在(verify-only)。 |
| Cloudflare Tunnel 搭配 Access | signed-jwt — 本地校验 Access 身份令牌 | 本地校验的 Access 身份 JWT(Cf-Access-Jwt-Assertion,RS256,issuer,audience,email,非空 sub)。不是图省事的 email 头,不是服务令牌,也不是「主机名是私有的」。 | 你自己配置 Access 应用,并让它只指向网关。安装过程校验本地 JWT 设置(routeManagement: verify-only);它无法独立证明 Access 始终挂在隧道上。 |
| Headscale 经 Tailscale TCP Serve | gateway-credential — 持有网关密钥 | 持有按操作员签发的、各不相同的高熵网关凭证。TCP Serve 只提供私有可达性;它没有 HTTP 身份头,也无法证明你是谁。 | 可以创建一条缺失的、指向 127.0.0.1:3088 的私有 TCP Serve 转发(ensure),或者只检查它是否存在(verify-only)。TLS 证书和密钥由你提供。在 Tailscale.com 上安装会引导你改用带身份识别的 Tailscale Serve。 |
| EasyTier | gateway-credential — 持有网关密钥 | 持有各不相同的高熵网关凭证。EasyTier 只负责传输。 | 未随附。 |

私有可达性不等于授权。tailnet 成员、可公网路由的 Cloudflare 主机名、或 mesh 对等节点都能连到端点,但只要网关允许列表不匹配,照样收到 403。

Cloudflare 的细节:受 Access 保护的应用往往能从公网访问。数据包可能未经认证就到达。支持的产品形态是身份门控应用加强制本地 JWT 校验,绝不是匿名公网隧道。本地令牌校验很可靠。没有大范围账户凭证,网关无法用机器证明 Access 始终挂在隧道上;安装过程会说明这一点,并且仍然拒绝缺失或无效的 JWT。

这个插件不做什么

- 不让 DSH 本身支持多租户,也不削减允许列表内用户的权限(每个允许的主体都是完整的 DSH 管理员)。
- 不把设备、节点或 mesh 成员身份当作人的身份。
- 不暴露可配置的通用反向代理,也不暴露任意可信头名称。
- 不支持公网匿名隧道、Funnel 或 Cloudflare 快速隧道。
- 不管理服务商级 ACL、DNS 区域或账户策略。
- 卸载时不会自动删除服务商的持久路由。
- 不接受用户自选密码。
- 不在一个网关实例里运行多个入口服务商。
- 不保护你免受同主机恶意管理员,或任何已经能读取 DSH 内存/配置、或直连 DSH 回环地址的进程。

每种认证模式能证明什么

这些 auth.mode 值就是 YAML 里的字面键名。每个值都固定搭配一个服务商,不能混用。

- trusted-header(仅 Tailscale)。 Serve 恰好注入一个 Tailscale-User-Login,且该值在允许列表里,形式为 login:<exact-login>。请求头名称写死在代码里,你没法配置成通用请求头。
- signed-jwt(仅 Cloudflare Access)。 请求恰好携带一个 Cf-Access-Jwt-Assertion,它要通过团队 JWKS 校验,并满足配置的 issuer 与 application audience,同时具备必需的 exp/iat/nbf、身份 type、标量 email,以及非空的 sub。允许列表用 email:<exact-email>。CF_Authorization cookie 永远不被信任。
- gateway-credential(Headscale TCP Serve)。 持有按操作员签发的独立 ≥256 位凭证(由命令行生成,不是用户自选的密码),从 JSON API 或同源登录表单以 POST body 提交——绝不用 URL 查询参数——再换取短期 __Host- 会话 cookie(HttpOnly、Secure、SameSite=Strict)。网关只存验证器哈希;会话可逐个吊销,尝试次数受限流,但不会永久锁定。TCP Serve 不提供身份:能连上节点不等于已授权。Tailscale Serve 和 Cloudflare Access 都无法选用这个模式。

安装之后

dsh-gateway doctor
dsh-gateway credential issue --store /path/to/dsh-one-gateway/credentials.json --name operator-1
dsh-gateway credential list --store /path/to/dsh-one-gateway/credentials.json
dsh-gateway credential revoke --store /path/to/dsh-one-gateway/credentials.json --name operator-1

在生成的配置档条目上设 enabled: false,再重启 DSH,即可停用。卸载不会移除 Tailscale Serve 路由、Cloudflare 隧道、Access 应用或凭证文件。这些要你自己清理。

威胁模型与本地主机信任边界

网关防御的是:伪造的身份请求头、public 模式下的服务商配置、Host/Origin/请求目标走私、服务商 token 泄漏进 DSH、过期的 JWT 密钥,以及会扩大暴露面的配置笔误。详见 SECURITY.md。

它不防御同一主机上能连到 127.0.0.1:3080 或 127.0.0.1:3088、能读 DSH 配置档、或以本地 root 身份行动的进程。回环 TCP 无法证明是哪个本地可执行文件打开的连接。同主机失陷不在防护范围内。

TLS、密钥与凭证

- 配置档 YAML 从不包含私钥、JWT 或已签发凭证的密钥。
- Cloudflare 签名密钥通过有界 HTTPS 从团队源站 JWKS 路径获取;不会写进配置档。
- Headscale TCP Serve 需要操作员提供证书和私钥(绝对路径、私钥权限收紧、配对匹配、未过期、SAN 覆盖 externalOrigin)。网关不生成 CA,也不自签名证书。客户端必须为该证书登记信任。
- 网关凭据(启用时)只在运维人员提供的绝对路径下存一个校验值,权限收紧。原始密钥只显示一次。
- 像备份其他密钥文件一样备份凭据存储;吊销按主体逐个进行。会话存在内存里,网关进程一重启就没了。

故障排查

不要为了「先跑起来」就关掉认证、Origin 校验、TLS 或服务商验证。

| 现象 | 检查什么 |
| 网关一直不就绪 | dsh-gateway doctor;Tailscale Serve 冲突/Funnel;TCP Serve 冲突/Funnel;TLS 证书/密钥;Cloudflare JWKS 拉取;allowlist 缺失 |
| 预期用户拿到 403 | 主体必须精确、区分大小写(login: / email:);身份头重复;POST/API/WebSocket 缺 Origin |
| 安装拒绝写入 | 已存在 dsh-gateway 或旧版 dsh-tailscale-gateway 条目;YAML 不是列表;缺 --yes 的值 |
| 挂了 Cloudflare Access 仍 403 | 身份 token 缺失/过期;audience 不对;服务 token(没有 email);Access 没挂上(探测可能报 unprotected) |

暂不支持

这些以后可能落到同一套契约上。光说「它是个 VPN」不够。

- EasyTier / ZeroTier / 仅 WireGuard —— 没有应用层身份(映射方式是 gateway-credential)。这三者今天都不支持,原因相同:这套代码目前无法证明监听器只绑在私有 overlay 接口上,而不只是它自己报告了正确的本地地址。Linux 和 macOS 有 SO_BINDTODEVICE / IP_BOUND_IF 可以做这件事;Node 的 net.Server.listen() 两个都不暴露。这是一个具体的工程缺口,不是说这些传输方式不能用。它们没有已发布的适配器,也没有排期承诺。
- Headscale HTTPS Serve —— 仍然卡住。Headscale 不提供 Tailscale 那种带身份感知的 HTTPS Serve。已发布的 Headscale 路径是裸 TCP Serve 加 gateway-credential,再加运维人员提供的证书,不是伪造身份头。
- NetBird —— 在拿出有出处的覆盖配置档和集成测试之前,它声称的身份头不予支持。
- Twingate / Pangolin —— 没有冻结的 JWT/头校验配置档。
- 通用反向代理 / 任意可信头 —— 太容易配出一个可伪造的头。
- 裸 LAN、SSH 隧道、公网隧道 —— 不在私有入口契约范围内。

旧的 dsh-tailscale-gateway 包仍是仅限 Tailscale 的参考产品。两个网关进程不能同时绑定同一个固定网关端口。安装时会检测到旧版配置档条目,并拒绝再追加一个。

配置

只接受下面列出的确切字段。未知键会报错。没有 listenHost、listenPort、upstream、headerName、jwksUrl、allowAnonymous、trustPrivateNetwork、public 或 funnel 这些键。
Tailscale — trusted-header 表示 Serve 会注入登录信息;routeManagement: ensure 表示安装过程会创建一条缺失的私有 Serve 路由:

enabled: true
externalOrigin: 'https://gateway.example-tailnet.ts.net:8443'
provider:
type: tailscale-serve
routeManagement: ensure
auth:
mode: trusted-header
trustedPrincipals:
- 'login:operator@example.invalid'

Headscale TCP Serve — gateway-credential 表示持有生成的密钥即可通过;TCP Serve 只提供私有可达性。tls 为必填:

enabled: true
externalOrigin: 'https://gateway.example.invalid:8443'
provider:
type: headscale-tcp-serve
routeManagement: ensure
tls:
certPath: '/path/to/dsh-one-gateway/cert.pem'
keyPath: '/path/to/dsh-one-gateway/key.pem'
auth:
mode: gateway-credential
trustedPrincipals:
- 'credential:operator-1'
credentialStorePath: '/path/to/dsh-one-gateway/credentials.json'

Cloudflare — signed-jwt 表示网关在本地校验 Access 身份 JWT;routeManagement: verify-only 表示 Access 由你自己挂载:

enabled: true
externalOrigin: 'https://dsh.example.invalid'
provider:
type: cloudflare-access
routeManagement: verify-only
teamOrigin: 'https://team.example.invalid'
applicationAudience: 'replace-with-access-application-audience'
auth:
mode: signed-jwt
trustedPrincipals:
- 'email:operator@example.invalid'

License

MIT。见 LICENSE。
预览分享卡片长什么样 ↓TiantianFlow/dsh-one-gateway
分享 · DeepSeek Harness Hub
TiantianFlow/dsh-one-gateway

把 DSH Web 分享给你指定的人,而不是整个网络。

这是你的仓库?认领条目

回到顶部