把容器端口一键发布成带口令的公网链接
29.5/100
综合分
0
GitHub 星标
—
npm 周下载
—/5
用户评分
数据截至 2026/11/2 · 周下载取自 npm 全网(含 CI / 镜像),非本站安装数;综合分由星标、活跃度与兼容性检查合成。
相关生态插件(非 dsh 原生,按其对应运行时安装)
git clone https://github.com/SOVLOOKUP/dsh-tunnel-preview.git状态速览
判定依据:实装验证 · 静态安装检查 · 自动扫描 · 仓库维护状态信任档位:仅索引
是什么
生态应用
桌面端 / Web 外壳,不以 dsh plugin add 安装
装得上吗
本站尚未做安装检查
安全吗
本站尚未对该插件做风险分级
暂未覆盖,不等同于无风险
还在维护吗
活跃:最近一次提交在 5 天前
档位由哪些信号合成
本站实装验证(真实安装 L4 覆盖全站;L5 为运行时冒烟或实机截图,覆盖范围小于 L4) · 验证所用 dsh 版本 · 静态安装检查 · 风险分级 · 仓库维护状态。 下方各区块是它的证据明细。
社区实装还没有人打卡 · 装过的第一个就是你
安全扫描自动 · 静态分析源码v2.7.0🔵 扫描:含敏感能力尚无人工评估展开查看扫描说明与证据 ↓
安全扫描自动 · 静态分析源码
v2.7.0静态扫描发现插件具备触达本地系统的能力:执行外部命令、读写/删除本地文件、读取剪贴板或密钥类环境变量(至少其一)。这是能力清单,不是危险判定——具体能力项与证据见下方,安装前请自行判断是否需要。
可执行外部命令写入剪贴板(不计风险)读取剪贴板或密钥环境变量发起外部网络请求
查看扫描证据(共 10 处,展示前 10 条)
- 发起网络请求index.js:197
const req = mod.request( - 发起网络请求index.js:239
const res = await fetch(url, { ...init, headers, signal: AbortSignal.timeout(15000) }); - 读取密钥环境变量index.js:398
if (process.env.DP_TOKEN) return process.env.DP_TOKEN.trim(); - 执行外部命令来自配置/变量index.js:526
const child = spawn(cfg.cloudflared, ['--no-autoupdate', '--config', cfg.tunnelConfig, 'tunnel', 'run'], { - 执行外部命令来自配置/变量index.js:571
const child = spawn(cfg.cloudflared, ['tunnel', 'route', 'dns', cfg.tunnelName, host], { - 发起网络请求index.js:693
const up = http.request( - 发起网络请求lib/client.js:712
const res = await fetch('/dsh-tunnel-preview/services', { cache: 'no-store' }); - 发起网络请求lib/client.js:754
const res = await fetch('/dsh-tunnel-preview/register', { - 发起网络请求lib/client.js:783
const res = await fetch('/dsh-tunnel-preview/unregister', { - 写入剪贴板lib/client.js:812
navigator.clipboard.writeText(url).then(() => {
扫描于 2026/11/2(1 天前) · 范围 入口闭包 + 发布文件清单 · 来源 GitHub 仓库
静态扫描只反映源码中出现的调用,不构成安全背书;人工评估与自动扫描相互独立、互不覆盖。
依赖的 DSH / Cordis 模块
@deepseek-ai/schemastery给这个插件打分还没有人投票↓
用户评分
还没有人投票,来当第一个
README
由 DeepSeek 最新模型翻译生成dsh-tunnel-preview
给智能体一把「开/关公网入口」的钥匙:把容器里正在监听的端口登记成 https://<端口>.<你的域名>,用完自己注销。复用已有的 Cloudflare 命名隧道,不新增对外端口,不需要人来改配置。
它做三件事
1. 反代:插件监听 127.0.0.1:9999(listen 可改),隧道的 catch-all 指向它;它按 Host 里的端口号把请求转发到 127.0.0.1:<端口>。HTTP 与 WebSocket(HMR)走同一条路径,所以改代码的热更新在公网链接上也是通的。
2. 登记表:只有登记过的端口才会被转发,登记表落盘在 stateDir/previews.json,宿主重启不丢。没登记的端口 403,登记完注销立刻恢复 403。
3. 闸门:URL 不带 token 打不开(容器内直连 127.0.0.1 除外)。用 ?dp_token=<token> 验一次就换成一个域级 Cookie,之后所有端口子域都免 token,浏览器里点一次就够。
工具
| 工具 | 作用 |
| preview_register({ port, label?
展开完整文档(README 剩余 1 节)
dsh-tunnel-preview
给智能体一把「开/关公网入口」的钥匙:把容器里正在监听的端口登记成 https://<端口>.<你的域名>,用完自己注销。复用已有的 Cloudflare 命名隧道,不新增对外端口,不需要人来改配置。
它做三件事
1. 反代:插件监听 127.0.0.1:9999(listen 可改),隧道的 catch-all 指向它;它按 Host 里的端口号把请求转发到 127.0.0.1:<端口>。HTTP 与 WebSocket(HMR)走同一条路径,所以改代码的热更新在公网链接上也是通的。
2. 登记表:只有登记过的端口才会被转发,登记表落盘在 stateDir/previews.json,宿主重启不丢。没登记的端口 403,登记完注销立刻恢复 403。
3. 闸门:URL 不带 token 打不开(容器内直连 127.0.0.1 除外)。用 ?dp_token=<token> 验一次就换成一个域级 Cookie,之后所有端口子域都免 token,浏览器里点一次就够。
工具
| 工具 | 作用 |
| preview_register({ port, label? }) | 建 DNS 记录(API 优先,退回 CLI)+ 入登记表,返回可直接打开的链接 |
| preview_unregister({ port }) | 出登记表,公网入口立刻 403;绑定了 API token 时顺带删 DNS 记录 |
| preview_list() | 列出所有登记项:端口、公网地址、本地服务还在不在听 |
登记前服务必须已经在听(插件读 /proc/net/tcp{,6} 的 LISTEN 套接字判断),否则登记出来的链接是 502——先起服务,再登记。
GUI:右侧栏「服务」标签与快捷入口
插件为 DSH Web 界面提供了内置伴生前端:
1. 右侧栏「服务」标签(Services Tab):
- 位于 DSH 右侧栏标签页,图标为专用服务/网络地球标;
- 服务卡片一览:实时展示所有通过隧道暴露的端口、备注、公网域名与创建时间;
- 在线状态检测:动态检测本地端口监听状态(🟢 正常监听 / 🔴 端口未监听);
- 一键快捷操作:
- 🚀 新标签打开:浏览器新窗口直接打开免密分享链接;
- 🌐 侧栏并排预览:与内置浏览器标签页联动,在右侧栏内并排预览;
- 📋 复制链接:带弹性动效与“已复制 ✓”浮动反馈;
- 🗑️ 注销服务:一键安全注销并切断公网访问(若绑定 Cloudflare Token 则自动清理 DNS 记录);
- 快速暴露新端口:支持自动探测容器内当前正在监听的本地端口(如 :3000、:8000),支持一键快速暴露;
- 隧道与 DNS 状态:底部常驻提示 Cloudflare 隧道连接状态与 API 绑定情况。
2. 会话顶栏快捷入口:
- 会话右上角工具条常驻「暴露的服务」图标按钮,点击直接展开右侧栏并聚焦到「服务」标签。
3. REST API 扩展:
- GET /api/tunnel-preview/services:获取当前暴露服务、候选端口与隧道状态;
- POST /api/tunnel-preview/register:动态暴露端口 { port, label };
- POST /api/tunnel-preview/unregister:动态注销端口 { port }。
配置
见 cordis.patch.yml,全部有默认值:
| 键 | 默认 | 说明 |
| listen | 9999 | 反代监听地址,必须与隧道 config 的 catch-all 一致 |
| domain | example.com | 子域后缀(主域名)。设置页「公网域名」可改,保存立即生效 |
| stateDir | $HOME/devpreview | token、previews.json 落盘目录 |
| tunnelName | dsh-dev | cloudflared tunnel route dns 用的隧道名 |
| cloudflared | $HOME/bin/cloudflared | 可执行文件 |
| tunnelConfig | $HOME/.cloudflared/config.yml | 隧道 config |
| manageTunnel | true | 托管 cloudflared 进程:宿主退出一起走,崩了自动重连(最多 5 次) |
| manageDns | true | 登记时自动建 CNAME(已存在视为成功) |
| deny | VNC/调试端口 | 永不公开的端口 |
| rewriteHost | true | 改写 Host/Origin/Referer,避免 dev server 的 host 校验拦截 |
| cookieMaxAge | 2592000 | 域级 Cookie 有效期(秒) |
| minPort | 1024 | 允许公开的最小端口 |
| cloudflareApiToken | 空 | 粘贴即绑定:插件自己校验 token、自己找 zone,之后 DNS 记录能建也能删。字段是 secret + volatile:读回不回显明文,保存只热更新、不重挂插件 |
| cloudflareZoneId / cloudflareAccountId | 空 | 一般留空,自动探测 |
| dnsOnUnregister | delete | 注销时的 DNS:delete 删(需已绑定 token)/ keep 留 |
用哪个域名
预览地址是 https://<端口>.<domain>。域名不写死在代码里,在插件设置里改:
1. 打开 DSH 侧栏 → 插件 → tunnel-preview。
2. 在表单最上面的 「公网域名」 填主域名,不要带 https:// 和端口,例如 example.com。
3. 点 保存。domain 是 volatile 字段:宿主只更新这一项并重跑绑定,不重载插件。已填 token 时会按新域名重新查 zone。
出厂默认值来自插件自带 cordis.patch.yml 里的 domain: example.com。如果你在 profile 的 cordis.patch.yml 里给 tunnel-preview 写了 config,loader 会整对象覆盖:以那一份里的 domain 为初始值,插件自带的这份不再生效。之后仍以设置页保存的值为准。
在设置里一键绑定 Cloudflare
不绑定也能用:建记录走 cloudflared tunnel route dns,只是删不掉。要让插件自己管 DNS:
推荐方式:官方模板一键直达(免手动勾选权限)
1. 进 DSH 侧栏 → 插件 → tunnel-preview,点击设置表单上的 「⚡ 直达 Cloudflare 生成 Token ↗」,或直接打开预置权限直达链接: Cloudflare API Token 预填创建页(已自动预选好 Zone → DNS → Edit 与 Zone → Zone → Read 权限,名称预设为 DSH-Tunnel-Preview)
2. 页面底部点击 Continue to summary → Create Token
3. 点击 Copy 复制生成的 Token,回到 DSH 插件设置页粘贴并保存即可!
保存即热生效(不重挂插件):宿主只更新 domain 和那三个 Cloudflare volatile 字段并重跑绑定。preview_list() 顶部会显示 Cloudflare API:已绑定(zone example.com …);失败也在这里写明原因(token 无效 / 缺 Zone.Zone Read / 网络不通),不会静默降级。
表单只认四个顶层字段(domain / cloudflareApiToken / cloudflareAccountId / cloudflareZoneId)。
旧的嵌套 cloudflare: { apiToken, accountId, zoneId } 仍能被读到,但只要 patch 里写过任一平铺字段,就以平铺为准。token 落在 profile 的 patch 里,字段标了 role('secret'):设置页与远程调用方读回时是占位符,不回显明文。
绑定后行为变化:
- preview_register 直接打 API 建记录,不再依赖 ~/.cloudflared/cert.pem;
- preview_unregister 顺手删掉记录(dnsOnUnregister=delete),公网零残留;
- 记录已存在但指向别的隧道时不覆盖,如实报错——不静默改别人的解析。
已知取舍
- DNS 记录删不删,看有没有绑定:未绑定 API token 时建记录只能走 CLI,于是只建不删(留着无害,通不通由登记表决定);绑定后默认 dnsOnUnregister=delete,注销即清干净。
- DNS 失败不阻塞登记表:建/删记录是尽力而为。Cloudflare API 打不通时,登记照做、注销照做(登记表里删掉那一行,公网立刻 403),只是 tool 输出与 GUI 会明说「记录没删掉」。
早先的版本在这里会直接抛错,导致点「注销服务」整条链中断——看着就是「点了没反应」。
- 容器里的 HTTPS_PROXY 会掐掉 api.cloudflare.com:开了 NODE_USE_ENV_PROXY=1 的宿主里,fetch 与核心 http/https 都会走 HTTPS_PROXY;白名单式代理对 Cloudflare API 常常直接断 TLS(fetch failed / socket disconnected before secure TLS connection),而直连 CF 边缘是通的。所以 API 客户端在代理失败时会用 agent: false 直连重试一次(见 makeCfClient)。
- 公网可见:这是真的公网入口,token 只挡「猜不到」的人。要让陌生人彻底进不来,应在 Cloudflare 侧加 Access 策略,而不是依赖这里的 token。
- 只支持一级子域:5173.example.com 可以,5173.dev.example.com 不行(Universal SSL 只覆盖一级子域,二级要付费 ACM)。
迁移自手写脚本
这套逻辑原先散在 /workspace/devpreview/{dispatcher.mjs,start.sh,addport.sh}。
装插件前先停掉旧栈,否则 9999 被占:
/workspace/devpreview/start.sh stop
之后 dispatcher 与 cloudflared 都由插件托管,addport.sh 的职责换成 preview_register 工具。旧的 .token 继续被复用,已发出去的链接不会失效。
测试
node --check index.js && node --test test/
- test/host.test.mjs:纯函数(Host 解析、端口白名单、cookie、隧道 UUID、schema 兜底)
- test/cloudflare.test.mjs:本地起一个 Cloudflare API 桩,跑绑定、建记录幂等、指向冲突、删记录、缺隧道 UUID —— 不碰真 Cloudflare,也不要求有 token预览分享卡片长什么样 ↓
分享 · DeepSeek Harness Hub
SOVLOOKUP/dsh-tunnel-preview
把容器端口一键发布成带口令的公网链接
相关插件 · 其他
模型破甲清洗YuJunZhiXue/dsh-purge
⚔️ DeepSeek Harness 网络安全红队工具dsh-purge
★ 16,148已汉化DeepSeek 客户端
73
女娲蒸馏alchaincyf/nuwa-skill
输入名人名字,提炼其思维模型与决策方式供你调用
★ 37,308已汉化DSH
72
逆向分析桥接Fanqi89/dsh-rea
REA(Reverse Engineer Anything)MCP 桥接,用来把 REA 逆向工具接入 DSH 插件
★ 51已汉化DSH
72
语音女友beiyege-01/dsh-voice-ai-girlfriend
语音 AI 女友Voice AI girlfriend for DeepSeek Harness:Whisper…
★ 888已汉化DSH
71.6
红队越狱测试套件Minglink/dsh-infinite-gen-5
DeepSeek v4.1 flash 逆向工具无限五代 求 Star 收藏 ⭐欢迎大家提交项目的改进
★ 3,759已汉化DSH
71.4
协同办公空间dream-num/univer-workspace
一个让人类与 AI Agent 共同创作、协作和审阅的开源 Office 工作空间。
★ 2,266已汉化DSH
70.7
这是你的仓库?认领条目