DSH Plugins Marketplace

DSH Plugins

Plugins

/

dsh-cloudflared-manager

9

dsh-cloudflared-manager

Discovered

Cloudflare Tunnel + 本地服务管理器(DSH 插件):Named 隧道增删改查、DNS 自动同步、本地服务启停/日志/源码编辑、快速隧道临时公网

Machine translated

dsh-cloudflared-manager

Cloudflare Tunnel + 本地服务管理器,作为 DeepSeek Harness(DSH)插件使用。

把本机的服务通过 Cloudflare 隧道暴露到公网,并在 DSH 面板里直接启停、看日志、改源码 —— 不需要记一堆命令,也不用开终端。


功能

Named 隧道(固定域名)

  • 增删改查 ingress 映射(hostname → 本地端口),写入云端并自动重载
  • 配好 API Token 后自动创建/删除 DNS CNAME 记录
  • 支持多个根域名(按 hostname 后缀自动匹配对应 zone)
  • 一键启停,可设为 DSH 启动时自动拉起

本地服务管理

  • 用自定义命令定义服务(名称 / 端口 / 启动命令 / 工作目录 / 备注)
  • 启动、停止、重启、看日志(面板内 tail)
  • 自动探活:PID 文件 + 端口探测 + 进程命令行匹配,三种手段兜底
  • 支持无端口服务(如 ssh 反向隧道守护、常驻 worker)
  • 停止时连同子进程一起清理(避免 ssh 之类的孤儿进程占住端口)
  • 在线查看/编辑服务的启动脚本,保存后点重启即生效
  • 每个服务可写一行备注说明用途,点服务名弹出查看

快速隧道(trycloudflare)

  • 无需 Cloudflare 账号,一条命令把本地端口暴露到临时公网 URL
  • 可选 URL 改写代理:直连 trycloudflare.com 在部分网络下不可达时,可配置自己的代理前缀,面板会额外给出代理地址(默认关闭)

安装

从 npm 安装(推荐)

dsh plugin --profile web add dsh-cloudflared-manager

装完重启 DSH 即可。这条路径依赖包内的 cordis.patch.yml 和 package.json 的 dsh.bundle.patch 字段——两者都随发布产物一起分发,不需要手工改 profile。

若 dsh plugin 报 declares no dsh.bundle,说明装到的版本低于 1.2.0,升级后再试。

从 GitHub 安装

dsh plugin --profile web add github:96bearli/dsh-cloudflared-manager

从本地源码安装

git clone https://github.com/96bearli/dsh-cloudflared-manager.git
dsh plugin --profile web add /path/to/dsh-plugin-cloudflared-manager

安装后重启 DSH,会话头部会出现「🌐 隧道」按钮,面板停靠在右侧边栏。

手动部署(不用 dsh plugin 命令)

整包放在 profile 的 node_modules 下即可,同一个目录同时承担两件事: host 端 require 从这里加载(package.json 的 main 指向 plugin/index.js), client 端的 client.js 也由这里提供给浏览器。

DEST=$DSH_HOME/profiles/web/node_modules/dsh-cloudflared-manager
mkdir -p "$DEST"
cp -r package.json README.md LICENSE cordis.patch.yml plugin runtime-examples "$DEST"/

不同 DSH 版本的 profile 布局可能不同。用这条命令确认本机该放哪:

dsh plugin --profile web add <本包路径>   # 装一次,看它落在哪
ls -d $DSH_HOME/profiles/*/node_modules/dsh-cloudflared-manager

早期版本曾要求分别在 profiles/web/plugins/(client)和 profiles/node_modules/ (host)各放一份,现已不需要;两份并存反而容易版本不一致——症状是改了代码 却不生效,或 API 报 unknown method。

然后在 $DSH_HOME/profiles/web/cordis.patch.yml 的 insert 列表里加:

- insert:
    - id: dsh-cloudflared-manager
      name: dsh-cloudflared-manager

重启 DSH web 进程生效。注意 host 端(plugin/index.js)改动必须重启, 只改 plugin/client.js 的话刷新浏览器即可。


运行环境

当前版本只支持 Linux x64,并且是按 Docker 容器环境调优的。

cloudflared 二进制路径与自动安装的 npm 包名都写死为 Linux x64:

<运行目录>/node_modules/@farthershore/cloudflared-linux-x64/bin/cloudflared

没有做 process.platform / process.arch 判断——这是有意的取舍:本项目在 Docker 容器(PID 1 为 tini)里运行,容器内固定是 linux/amd64,硬编码换来的是 更少的运行期分支。在 macOS / Windows / ARM 上安装会拿不到可用的二进制。

容器环境下有三处专门处理:

事项处理
/tmp 是 tmpfs(内存盘,容器重启即丢)日志统一写 <运行目录>/logs/,与 PID 文件同处持久卷
容器内存有限,日志不该吃内存同上,落磁盘而非 tmpfs
pts / 进程树与宿主机隔离进程探活与停止全部走 /proc 与 PID 文件,不依赖 ps/pgrep

若要在其他平台使用,需要自行修改 CLOUDFLARED_BIN 与 ensureCloudflared() 里的 包名(如 cloudflared-darwin-arm64),并验证进程探活逻辑。


配置

运行目录默认为 $DSH_HOME/cloudflared-setup/(可用环境变量 DSH_CF_SETUP 覆盖):

$DSH_HOME/cloudflared-setup/
├── cf_config.json      # API Token + 账号级配置(敏感,600 权限)
├── config.yml          # Named 隧道本地配置备份
├── credentials.json    # 隧道凭证(敏感)
├── services.json       # 本地服务定义
├── pids/               # PID 文件
└── logs/               # 隧道与服务日志(放持久卷,容器重启不丢)

cf_config.json 的字段说明见 runtime-examples/cf_config.json.example。

⚠️ cf_config.json 和 credentials.json 含密钥,权限设为 600,绝不要提交到 git。

获取 Cloudflare 凭据

  1. API Token:Cloudflare 控制台 → My Profile → API Tokens → Create Token,权限需含:
    • Zone → DNS → Edit
    • Zone → Zone → Read
    • Account → Cloudflare Tunnel → Edit
  2. Account ID:控制台右侧栏,或任意 zone 的 URL 里那串 32 位十六进制。
  3. Tunnel ID:Zero Trust → Networks → Tunnels 里点进隧道可见。
  4. 根域名白名单:填你要用的根域名,如 example.com(不要填子域名)。

也可以在面板的「设置 → Cloudflared 隧道」页签里填写,不用手动改 JSON: 设置页有独立的「根域名白名单」区,可逐个添加/移除,并点「校验可用性」现场确认 每个域名能否写 DNS。

credentials.json 不需要手工准备。 全新安装时运行目录里没有这个文件, 首次点「启动」时插件会自动生成它:调用 Cloudflare 的 GET /accounts/{accountId}/cfd_tunnel/{tunnelId}/token(要求 Token 含 Account → Cloudflare Tunnel → Read),把返回的隧道 token 解出来就是 { AccountTag, TunnelID, TunnelSecret },即 credentials.json 的三个字段, 生成后权限自动设为 600。

因此只要 API Token + Account ID + Tunnel ID 三项填对,Named 隧道就能直接跑起来。 没配 Token 时插件会在面板上明确提示,并保留手工路径:用该隧道的 token 执行 cloudflared tunnel run --token <TOKEN>,或从已有部署拷一份 credentials.json。 文件里的 TunnelID 与当前 tunnelId 不一致时(换过隧道、或拷了别人的文件), 启动时同样会自动重建。

不需要填 Zone ID。 插件按域名后缀自动解析对应的 zone(要求 Token 有 Zone:Read 权限)。zoneId 字段已废弃:旧版用它做「解析不出 zone 时」的兜底 放行,但单个 zoneId 只能对应一个 zone,拿它去建另一个首级域名的记录会让 Cloudflare 把 hostname 当成该 zone 的子域(落库成 xxx.other.tld), 正是历史上「映射建歪」的成因。现在白名单是唯一边界。

关于 DNS 与 ingress 的一致性

新增/删除映射都是两步且非原子:

  • 新增:先写 tunnel ingress,再建 DNS CNAME
  • 删除:先删 ingress,再删 DNS CNAME

如果第二步失败(例如 Token 缺 Zone:DNS 权限),会出现半完成状态并留下痕迹:

场景后果
新增时 DNS 失败映射已在隧道里,但域名解析不到 —— 访问无响应
删除时 DNS 失败Cloudflare 里残留一条指向 xxx.cfargotunnel.com 的 CNAME

面板会明确报出这类情况(而不是笼统显示"成功")。看到提示后请到 Cloudflare DNS 面板核对并手动清理,否则残留记录会一直指向已失效的映射。

传输协议(QUIC / HTTP2)

cloudflared 默认走 QUIC(UDP)。若本机 UDP 接收缓冲区偏小,QUIC 会频繁丢包: 连接数看着正常、日志里也有 Registered tunnel connection,但公网请求耗时在 2–15 秒之间剧烈抖动、大量直接超时,非常容易被误判成"目标站点慢"。

先看内核上限:

sysctl net.core.rmem_max        # 理想 7168 KiB

若远小于该值,在 cf_config.json 里加一行改用 TCP:

{ "protocol": "http2" }

插件每次启动都会重写 config.yml,会把这个字段原样写回(旧版本会把它丢掉, 导致手工加的设置在下一次「启动」后静默失效)。

关于 ingress 里的 localhost

插件写 config.yml 时会把 service 里的 http://localhost:PORT 自动改写成 http://127.0.0.1:PORT。

原因:多数 Linux 的 /etc/hosts 里 localhost 同时指向 127.0.0.1 和 ::1, cloudflared 解析后会优先用 ::1;而本地服务通常只监听 IPv4,于是连 [::1]:PORT 被拒,公网表现为 502。这一条很难查,因为隧道状态一切"健康", 日志里才有一行:

Unable to reach the origin service ... dial tcp [::1]:3082: connect: connection refused

确实要连 IPv6 服务时,可在映射的 service 里直接手填 http://[::1]:PORT—— 这种显式写法不会被改写。


使用

本地服务定义

services.json 是一个数组:

[
  {
    "name": "我的 Web 应用",
    "port": 8080,
    "command": "/usr/bin/node /opt/app/server.js",
    "cwd": "/opt/app",
    "autoStart": true,
    "note": "主站,对外 example.com"
  }
]
字段说明
name唯一名称
port探活用端口,可为 null(无端口服务)
command启动命令,建议写完整路径(DSH 的 PATH 不保证覆盖)
cwd工作目录
autoStartDSH 启动时是否自动拉起
note一行备注,面板里点服务名查看

新增服务时命令里带上脚本路径(如 /path/python main.py),「源码」按钮才能自动定位到文件。

面板操作

会话头部「🌐 隧道」→ 右侧栏面板,三个页签:

  • 域名映射:ingress 增删改查、DNS 自动同步、隧道启停
  • 本地服务:服务启停/日志/源码/编辑/删除、自动启动开关
  • 快速隧道:临时公网暴露

HTTP API

插件在 POST /dsh-cf/api 暴露 JSON API,请求体格式为 {"method": "...", "args": {...}}。

# 综合状态(最常用)
curl -s -X POST http://127.0.0.1:3080/dsh-cf/api \
  -H 'Content-Type: application/json' \
  -d '{"method":"cf-status"}'

# 带参数的调用:参数必须放在 args 里
curl -s -X POST http://127.0.0.1:3080/dsh-cf/api \
  -H 'Content-Type: application/json' \
  -d '{"method":"cf-svc-stop","args":{"name":"我的 Web 应用"}}'
分类方法
状态cf-status / cf-version / cf-probe
Named 隧道cf-named-list cf-named-add cf-named-update cf-named-delete cf-named-start cf-named-stop cf-named-auto-start-set
本地服务cf-svc-list cf-svc-add cf-svc-update cf-svc-note-set cf-svc-delete cf-svc-start cf-svc-stop cf-svc-restart cf-svc-log cf-svc-auto-start-get cf-svc-auto-start-set
源码cf-src-read cf-src-save cf-src-list
配置cf-cfg-get cf-cfg-set cf-cfg-test cf-cfg-auto-start-get cf-cfg-auto-start-set
根域名白名单cf-zones(列出账号下可选 zone + 当前白名单)cf-whitelist-add cf-whitelist-remove
快速隧道cf-maps cf-map-add cf-map-stop cf-proxy-prefix-get cf-proxy-prefix-set
生命周期cf-restart-dsh(SIGHUP 重启 DSH)

cf-whitelist-add/remove 与 cf-proxy-prefix-get/set 读写的是本地配置, 不需要 API Token;cf-zones 里"账号下可选 zone"那部分需要 Token 具备 Zone:Read,没配 Token 时它只回白名单本身,前端会自动退回手输域名。


本版本不含 CF 优选

本仓库是精简版,不包含 CF 优选 IP 扫描与子域名接入(opt-* API 与 optimize.js)。 需要那部分功能请使用完整版分支。


依赖

  • DSH >= 0.2.0
  • cloudflared 二进制(插件会自动下载;也可把二进制放到 vendor/ 下离线使用)
  • 无第三方 npm 依赖,也不依赖其他 DSH 插件

常见问题

服务显示「已停止」但进程在跑? 探活有三种手段:PID 文件、端口探测、命令行匹配。无端口服务只能靠命令行匹配,此时请确保 command 里有可辨识的脚本路径(如 /opt/app/server.js 而不是 node -e "...")。

改了 index.js 不生效? host 端代码在 DSH 启动时被 require 进内存,改完必须重启 DSH。client.js 只需刷新浏览器。

停服务后端口还被占着? 本插件会在停止时清理子进程(读 /proc/<pid>/stat 的 ppid 建进程树)。如果仍有残留,通常是服务自己 daemon 化了,需要按进程名单独处理。

域名打不开但隧道是健康的? 检查 DNS CNAME 是否指向 <tunnelId>.cfargotunnel.com 且已代理(橙云)。没配 API Token 时插件不会自动建 DNS 记录。

隧道显示健康、连接数正常,域名却全是 502? 502 表示隧道这一层通了、但后端没人应答:cloudflared 把请求转到了 ingress 里写的本地端口,而那个端口上没有服务在监听。本插件的「健康」只反映 cloudflared 与 Cloudflare 边缘之间的连接数(connections > 0),不代表后端存活。排查:看 cf-status 返回的 namedTunnel.ingress 里的端口列表,逐个 curl -o /dev/null -w '%{http_code}' http://127.0.0.1:<port>/(返回 000 即无服务监听),再把这些服务在「本地服务」页签里建好并启动。


License

MIT

Comments

Loading…

Similar plugins

dsh-service-portal

对外服务门户:装好即用,设置页内网/公网二维码扫码进控制台管理服务与路由(cloudflared 隧道 + 口令登录,内网免密可开密码、外网必须口令)。

Tools & CapabilitiesTerminal & ClientsManifest valid

★ 1

MIT

Python

dsh plugin --profile web add dsh-service-portal

by godchen520

DSH 手机/外网远程访问插件:免配置公网隧道 + 局域网 HTTPS 直连 + 自定义公网链接/端口 + 微信机器人

UI & ExperienceManifest valid

★ 19

↓ 348/wk

MIT

JavaScript

Oct 24, 2026

dsh plugin --profile agent add dsh-web-remote

by zergtant

DeepSeek Harness (dsh) 远程访问插件:提供 TLS、登录认证、会话保护和 HTTP/WebSocket 透明反代,支持局域网及 FRP ,cloudflare隧道等远程访问。

Development & InfrastructureManifest valid

★ 0

MIT

JavaScript

Sep 13, 2026

dsh plugin --profile web add dsh-remote-access

by CWNU-Open-Source-Community

DSH 远程访问插件:内网二维码 / cloudflared 隧道 / frp+自有服务器(含登录门户)

Tools & CapabilitiesManifest valid

★ 7

↓ 44/wk

JavaScript

Aug 16, 2026

dsh plugin --profile web add dsh-webgate

by ai-eks

Password-gated Cloudflare Tunnel access for the DeepSeek Harness Web GUI, with quick and named tunnel modes.

Tools & CapabilitiesTerminal & ClientsManifest valid

★ 4

↓ 271/wk

MIT

TypeScript

Oct 5, 2026

dsh plugin --profile web add dsh-auth-tunnel

by jxboop

给 DeepSeek Harness 用的手机端桥接插件:手机发图、下发任务、实时看输出,支持局域网 / USB 共享 / Cloudflare 隧道外网访问。

Security & AuditManifest valid

★ 0

MIT

JavaScript

Oct 23, 2026

dsh plugin --profile web add dsh-plugin-mobile-bridge