dsh-cftunnel

by weicy98

1 UI 增强github 检测到 manifest package.json#dsh收录于 08-16

dsh cf隧道UI,带token/邮箱验证

dsh cf tunnel ui with token/email verify

安装

dsh plugin --profile web add github:weicy98/dsh-cftunnel

GitHub 源码安装:首次需按提示配置 allowBuilds 构建授权后重试

安装与环境配置指引、插件开发教程见 DSH 中文社区文档 ↗

安装即在你的机器上以你的权限运行第三方代码——它可读写文件、使用凭据、访问网络,DSH 的工具审批不会为插件代码加沙箱。「检测到 manifest」仅代表发现 dsh.bundle / dsh.plugin 清单,不构成兼容性或安全审查;安装前请审阅源码,不熟悉的插件先在不含密钥的环境试用。

README

目录

English | 中文

DeepSeek Harness 的 bundle 插件:通过 Cloudflare Tunnel 把本地 web GUI(http://127.0.0.1:3080)暴露到公网。

装好插件,打开 Settings,填 Cloudflare 信息,点连接。 cloudflared 由插件自动下载管理——不用手动安装、不用包管理器、不用重启。

快速上手

  1. 安装——一条命令:

    dsh plugin --profile web add git+https://github.com/weicy98/dsh-cftunnel
    
  2. 重启 dsh web,打开 Settings → Cloudflare Tunnel。

  3. 选模式、填信息、点连接。 复制带 token 的访问链接分享出去。

首次连接会下载一次 cloudflared(约 40MB),慢网络可能要几分钟——面板里有进度条显示下载进度;

模式

按你手头有什么选:

模式 输入 URL 适合场景
快速隧道 无 随机 https://<名字>.trycloudflare.com 想立刻要个链接,不想配 Cloudflare 账号
隧道 Token 隧道 token + 域名 https://<域名> 已经在 Zero Trust 仪表盘建好了隧道
API Token API token + 隧道名 + 域名 https://<域名> 让插件自动建隧道、DNS,并可顺带开邮箱验证

端到端流程

  1. Settings 面板里选模式(快速隧道 / 隧道 Token / API Token),点 连接。
  2. 连接时插件先自动准备 cloudflared——$DSH_HOME/cloudflared/cloudflared 不存在就从 GitHub 官方 release 下载对应平台二进制并解压缓存。
  3. 启动隧道:
    • 快速隧道:cloudflared tunnel --url http://127.0.0.1:<proxyPort> → 随机 https://<名字>.trycloudflare.com。
    • 隧道 Token:cloudflared tunnel run,用 Zero Trust 仪表盘生成的 token(路由/ingress 在仪表盘配置)。
    • API Token:通过 Cloudflare HTTP API 自动创建隧道 + 配置 ingress + 建 DNS CNAME,再用返回的 token 运行(不需要 cert.pem,不需要本地 config.yml)。
  4. 所有隧道流量经本地反向代理(127.0.0.1:<proxyPort>):代理把 Host 改写为 loopback、删除 Origin,harness 信任围栏全放行(含特权方法)。代理前有访问 token 校验(默认开启)和可选的 Cloudflare Access 邮箱 OTP 两道门。
  5. 秘密(API token、隧道 token、代理访问 token)存凭据存储(~/.dsh/.credentials.yaml);非秘密偏好(模式、域名、隧道名、账户/Zone ID、邮箱验证设置)存 settings 命名空间(~/.dsh/settings.yaml),下次打开自动预填。

安装

在本目录下:

dsh plugin --profile web add file:.

或从 git / npm 源安装:

dsh plugin --profile web add git+https://github.com/weicy98/dsh-cftunnel
dsh plugin --profile web add dsh-cftunnel

dsh plugin 在 profile 目录执行 pnpm 并同步 dsh.profile.bundles——本包声明了 dsh.bundle.patch,所以会自动加进 bundle 栈。重启 dsh web,打开 Settings → Cloudflare Tunnel。

改代码后重新安装:先 dsh plugin --profile web remove dsh-cftunnel 再 add file:.(pnpm 把 file: 依赖视为不可变,remove + add 是最可靠的刷新方式)。

配置

部署级选项写在 profile 自己的 cordis.patch.yml(~/.dsh/profiles/web/cordis.patch.yml)或 --patch 覆盖层;其余都是 Settings 面板字段,持久化在 settings 命名空间。

- id: cloudflare-tunnel
  config:
    cloudflaredPath: 'cloudflared'   # 显式二进制路径(默认:自动下载到 $DSH_HOME/cloudflared)
    port: 3080                       # 要代理的本地 harness 端口
    downloadMirror: ''               # 可选 ghproxy 风格镜像前缀,如 'https://ghproxy.example/'
    proxyPort: 3091                  # 反向代理的 loopback 端口
    proxyAuth: 'token'               # 'token'(默认)| 'none'
    proxyToken: ''                   # 可选固定访问 token;留空 = 自动生成并持久化
    accessPolicy: 'none'             # 'none' | 'emailOtp'
    accessEmailDomains: []           # 如 ['yourcompany.com'] — 限制邮箱 OTP 发送域
    accessAccountId: ''              # 可选显式 Cloudflare 账户 ID
    accessZoneId: ''                 # 可选显式 Cloudflare Zone ID

说明:

  • downloadMirror 控制一次性下载方式。留空(默认)走 GitHub API → CDN——权威但在部分网络较慢(实测约 80 KB/s,40MB 约 8 分钟)。配镜像前缀可加速;镜像属于第三方,需信任其不篡改二进制。
  • accessAccountId / accessZoneId 也可以在设置面板里填,填了就不需要 API token 的 Account Settings:Read / Zone:Read 权限。
  • proxyAuth: 'none' 关闭访问 token 校验(UI 关闭前会二次确认)。

安全模型(重要)

所有隧道流量经本地反向代理(127.0.0.1:<proxyPort>),代理把请求改写为 loopback(Host → 127.0.0.1:<port>、删除 Origin),因此 harness 信任围栏完全放行——包括特权方法,远程访客获得与本机一致的完整体验。

代理只绑定 127.0.0.1,唯一入口是 cloudflared(Cloudflare edge)。它前面有两道独立门:

  • 访问 token(默认开启,proxyAuth: 'token'):每个请求必须带 token——首次以 ?token=… 带一次(代理随后种下 HttpOnly; Secure cookie),之后靠 cookie 自动携带。面板会显示可分享的带 token 链接,开关实时生效。
  • Cloudflare Access 邮箱 OTP(可选,accessPolicy: 'emailOtp'):edge 层邮箱验证,请求到代理前就被拦截。

建议:公网暴露时两道门都开。两道都关意味着任何拿到 URL 的人都能完全控制 harness(设置、凭据、目录选择器)——只在可信网络才可接受。

本机使用(http://127.0.0.1:3080)不经过代理,完全不受影响。

邮箱验证(Email OTP)

把 accessPolicy 设为 'emailOtp'(或在面板里勾选)即可用 Cloudflare Access 一次性 PIN 拦住隧道。连接时插件用同一个 API token 创建绑定该域名的 self-hosted Access 应用和 allow 策略:

  • 不配白名单:任何访客输入邮箱 → 收 6 位 PIN → 输入正确才放行。
  • 白名单填完整邮箱(user@example.com):精确邮箱规则(Access 里的 "Emails")。
  • 白名单填域名(yourcompany.com):邮箱域名规则(Access 里的 "Emails ending in")。

要求:

  • 仅 API Token 模式(quick / token 隧道的域名不由本插件程序化管理,无法自动挂策略)。
  • API token 额外需要 Access: Organizations, Identity Providers, and Groups:Edit;未配 accessAccountId 时还需要 Account Settings:Read 来解析账户 ID。

API token 权限清单

API Token 模式需要(面板里也有提示):

资源 权限 用途
Account Cloudflare Tunnel — Write 建隧道、配 ingress
Zone DNS — Edit 建 CNAME 记录
Account Account Settings — Read 解析账户 ID(填了 Account ID 可省)
Zone Zone — Read 解析 Zone ID(填了 Zone ID 可省)
Account Access: Organizations, Identity Providers, and Groups — Write 仅邮箱验证需要

前置条件

  • 带 web 界面的 profile(dsh web / --profile web)。
  • 隧道 Token 模式:Zero Trust 仪表盘生成的隧道 token,且公共域名路由到 http://127.0.0.1:3091(loopback 代理端口——路由到 3080 会绕过访问 token 门)。
  • API Token 模式:具备上述权限的 API token,且域名的 DNS zone 在该账户上。
  • 首次连接需要能访问 github.com(只用于下载 cloudflared,之后缓存)。

开发

pnpm install   # dsh-settings(dev/peer)、schemastery
pnpm test      # node --test(cfapi、cloudflared、主机生命周期、proxy 四套)

架构

关注点 位置 机制
准备 cloudflared lib/cloudflared.js GitHub release 下载 + tar 解压 + 缓存到 $DSH_HOME/cloudflared
运行/管理隧道 lib/index.js node:child_process spawn + ctx.effect 清理
Cloudflare API lib/cfapi.js cfd_tunnel 创建 + configurations ingress + dns_records CNAME + Access 应用/策略
Loopback 代理 lib/proxy.js Host 改写 loopback + 删 Origin + 访问 token 门(cookie / ?token=)+ WS 转发——零依赖(node:http + node:net,不再依赖 http-proxy / DEP0060)
依赖 package.json schemastery 作为叶子依赖;宿主 seam(dsh-settings)放 peerDependencies;engines.node >= 20.3
秘密 lib/index.js ctx.credentials(CLOUDFLARE_API_TOKEN、CLOUDFLARE_TUNNEL_TOKEN、CLOUDFLARE_TUNNEL_PROXY_TOKEN)
偏好 lib/index.js ctx.settings 命名空间 cloudflare-tunnel
Client→Host RPC 两端 ctx.connection.rpc.handle('/cloudflare-tunnel', …) / ctx.get('connection').rpc.call(…)
设置 UI lib/client.js ctx.slots.inject('settings.section', …) + locale 字典
Bundle 接线 cordis.patch.yml + package.json dsh 单行 insert,自动加入 dsh.profile.bundles

/cloudflare-tunnel 通道的端点:status、start、stop、setProxyAuth。start 接受 AbortSignal,UI 取消会中止正在进行的下载与 API 配置。

已知限制

  • 仅 web profile(node 半等待 connection、credentials、settings、webServer;headless/TUI 下保持休眠)。
  • 进程内有效:运行中的隧道不跨 harness 重启,但缓存的二进制、存储的秘密与偏好会保留;隧道、ingress、DNS 记录持久化在 Cloudflare 侧。
  • API token 只用于 Cloudflare API 配置调用(隧道/ingress/DNS/Access);运行中的 cloudflared 用隧道 token 认证,不用 API token。

原始 README: https://github.com/weicy98/dsh-cftunnel/blob/main/README.zh.md ↗