@zhangzhian/dsh-tunnel-core

中文文档
0.3.1发布于 2026/11/03MITTypeScriptES Module

dsh-tunnel 的组件包:把本机 sshd 通过 Cloudflare Quick Tunnel 暴露出去(host 半 + 设置页面板)

原始使用文档
文档目录7 节
  1. 安装
  2. 提供什么
  3. 要求
  4. English
  5. Install
  6. What it provides
  7. Requirements

English | 简体中文

@zhangzhian/dsh-tunnel-core

开发工具(@zhangzhian/dsh-devtools)的隧道组件:host 半身(隧道生命周期、sshd 体检、 系统服务、Remote API)+ 「远程接入」设置页。

不要单独装它 —— 装清单包 @zhangzhian/dsh-devtools,它会作为依赖自动拉下来, 在插件页上表现为「开发工具」卡片里的一行(不是另一张卡片)。

2026-10:原来有一个独立的清单包 @zhangzhian/dsh-tunnel(插件页上单独一张 「远程接入」卡片)。用户反馈「远程接入没和开发工具在一起」,于是把它并进了 dsh-devtools 的 patch —— 同一个包只能被一个清单 insert,否则宿主模块会跑两遍。

安装

dsh plugin --profile web add @zhangzhian/dsh-devtools

提供什么

  • dshTunnel Remote 命名空间 —— status / startSsh / stopSsh / startWeb / stopWeb / start / stop / probe / sshd / sshdEnablePlan / runSshdEnable / recipe / settings / updateSettings / installService / uninstallService / serviceState / doctor / credential / rotateCredential / setCredential,两端类型打通。 ⚠️ probe / doctor / installService / uninstallService / serviceState 不在面板上:它们是排查和运维用的。能力在、有测试,只是没有界面入口。
  • 隧道生命周期 —— 解析 cloudflared(显式路径 → PATH → 常见安装位置 → 按固定 版本下载)、带 --protocol http2 起进程、从 JSON 行的 logfile 里解析 Quick Tunnel 域名,并把每次状态变化落盘,所以 DSH 重启后面板还在。
  • 两条隧道各自独立 —— SSH 隧道(phase)和 dsh Web 隧道(webPhase)各有自己的 阶段、域名、句柄、开关和风险确认;exposeWeb 是"用户想不想开"的期望态,webPhase 才是"现在到底开没开"。
  • 公网入口凭据 —— 隧道 B 的代理前面挡着一对账号 + 密码(credential / rotateCredential / setCredential,落盘在 access-code,升级前那种"只有一行 明文密码"的文件照样读得出来);浏览器用 cookie 记 30 天,直达链接是 ?token=账号:密码。随机那一份是默认(8 位账号 + 24 位密码),也可以换成用户自己 填的:校验在 host 半(validateCredential,账号和密码里都不许有冒号 —— 直达链接 靠第一个冒号切分)。
  • 端口纪律 —— 客户端端口永远落在 2201–2299,而且对同一台宿主机是稳定的,所以 dsh-electron 那边只需要配一次。
  • 三平台服务定义 —— plistFor(LaunchAgent)、unitFor(systemd 用户 unit)、 taskXmlFor(计划任务)都是纯函数,所以虽然这里只能跑其中一个,转义规则在每个平台 上都有单测守着。
  • 零依赖二维码编码器 —— 客户端 bundle 只允许 require 平台提供的 9 个种子模块, 所以 qr.ts 是自己写的字节模式编码器,八个掩码都对着参考实现验证过。
  • 「还没开启远程登录」的引导 —— sshd 没在监听时,SSH 那一屏会给出本平台确切的 开启命令(macOS systemsetup -setremotelogin on;Linux systemctl enable --now ssh / sshd / ssh.socket,按发行版与是否 socket 激活探测;Windows Add-WindowsCapability + Set-Service sshd + Start-Service sshd),逐条可复制。 主按钮「在终端里执行」把命令预填进 dsh 自带的终端(TerminalView.write(),不带 换行),用户在自己的终端里按回车、输密码 —— 插件不提权、不碰 sshd_config, 无头服务器上照样能用。dsh 本身就是 root / 管理员时才多一颗「直接开启」。 已经在监听时这块不出现(判据是读到 SSH 横幅,不是"用户点没点过")。
  • 设置面板 —— 三个页签:dsh Web 隧道在前(也是默认那一屏)、SSH 隧道、 配置(两条隧道共用的端口与 cloudflared 路径,排在最后)。页签条通栏、吸顶在 页头下面,选中项下面一条 2px 下划线。dsh Web 那条装着访问地址 + 二维码(扫一下 直接进去,链接里带着账号密码)+ 可自定义的账号密码;SSH 那条只装客户端接入信息 (域名、命令、脚本、四步说明 —— 平台按浏览器自动判断,没有切换控件,也没有二维码); 配置那条就是四个端口 / 路径字段(一份草稿 + 一个保存)。两条隧道各一张卡片(各自的 状态轮询与开关)、各一份独立的开启前风险确认。体检 / 自检 / 服务 / 诊断包不在面板上 (见上)。

要求

  • Node.js 20+。 host 半只用 node:child_process、node:fs/promises、node:dgram (自检的 DNS 直查,见下)和 AbortController —— 没有原生模块,所以 Linux / macOS / Windows 上行为一致。
  • 一个 DSH 安装,其客户端半身提供那 9 个种子模块(react、react/jsx-runtime、 @deepseek-ai/dsh-client-ui-primitives 等)。其余依赖在构建期内联进 bundle。
  • cloudflared —— 在 PATH 里、在常见安装位置,或者被下载(带 SHA-256 校验)到 $DSH_HOME/dsh-tunnel/bin。
  • 一个在监听的 sshd,最好只允许密钥登录。没开的话面板会给出本平台的开启命令, 并在终端里预填好(见上);各系统的开法另见 @zhangzhian/dsh-devtools 的 README。

English

@zhangzhian/dsh-tunnel-core

The tunnel component of Dev tools (@zhangzhian/dsh-devtools): the host half (tunnel lifecycle, sshd inspection, system services, Remote API) plus the "Remote access" settings page.

Do not install it on its own — install the bundle package, which pulls this in as a dependency.

Install

dsh plugin --profile web add @zhangzhian/dsh-devtools

What it provides

  • dshTunnel Remote namespace — status / startSsh / stopSsh / startWeb / stopWeb / start / stop / probe / sshd / sshdEnablePlan / runSshdEnable / recipe / settings / updateSettings / installService / uninstallService / serviceState / doctor / credential / rotateCredential / setCredential, all typed end to end. ⚠️ probe / doctor / installService / uninstallService / serviceState are not on the panel: they are for troubleshooting and operations. The capabilities are there and tested, they just have no UI entry point.
  • Tunnel lifecycle — resolve cloudflared (explicit path → PATH → common install locations → pinned download), spawn it with --protocol http2, parse the Quick Tunnel hostname out of the JSON-lines logfile, and persist every state change so the panel survives a DSH restart.
  • Two independent tunnels — the SSH tunnel (phase) and the dsh web tunnel (webPhase) each own their phase, hostname, process handle, on/off button and risk acknowledgement; exposeWeb is the desired state, webPhase is what is actually on.
  • Public entry credentials — one username plus a password sit in front of tunnel B's proxy (credential / rotateCredential / setCredential, persisted in access-code; the pre-upgrade file holding a single plain-text password is still readable). Browsers keep a cookie for 30 days, and the direct link carries ?token=<user>:<pass>. The random pair is the default (an 8-character username and a 24-character password), and it can be replaced with one the user types: the validation lives in the host half (validateCredential, and neither the username nor the password may contain a colon — the direct link splits on the first one).
  • Port discipline — the client port always comes from 2201–2299, and it is stable for a given host, so dsh-electron only needs configuring once.
  • Platform services — plistFor (LaunchAgent), unitFor (systemd user unit) and taskXmlFor (Task Scheduler) are pure functions, so their escaping rules are unit tested on every platform even though only one of them can run here.
  • A dependency-free QR encoder — the client bundle may only require the platform's nine seed modules, so qr.ts is a self-contained byte-mode encoder validated against the reference implementation for all eight masks.
  • An "SSH is not enabled yet" guide — when sshd is not listening, the SSH tab prints the exact commands for this platform (macOS systemsetup -setremotelogin on; Linux systemctl enable --now ssh / sshd / ssh.socket, picked from the distro and whether socket activation is in use; Windows Add-WindowsCapability + Set-Service sshd + Start-Service sshd), each copyable. The primary button prefills the command into dsh's own terminal (TerminalView.write(), no trailing newline), so the user presses Enter and types the password in their own terminal — the plugin never elevates and never touches sshd_config, and it works on a headless server too. An "enable now" button only appears when dsh itself is root / administrator. The block does not appear when sshd is already listening (the criterion is reading the SSH banner, not "did the user click").
  • The settings panel — three tabs: dsh web tunnel first (and it is the default view), the SSH tunnel, and config (the ports and cloudflared path both tunnels use, last). The tab bar spans the full width, is pinned under the page header, and marks the selected tab with a 2px underline. The dsh web tab holds the URL plus a QR code (scan it and you are in — the link carries the credentials) and an editable username and password; the SSH tab holds only the client recipe (hostname, command, script, four steps — the platform is auto-detected, with no switcher and no QR code); the config tab holds the four port / path fields (one draft, one save). Each tunnel keeps its own card (its own status polling and switch) and its own risk confirmation. The check-up, self-test, service and diagnostics bundle are not on the panel (see above).

Requirements

  • Node.js 20+. The host half uses only node:child_process, node:fs/promises, node:dgram (the self-check's direct DNS query) and AbortController — no native modules, so it works the same on Linux, macOS and Windows.
  • A DSH install whose client half provides the nine seed modules (react, react/jsx-runtime, @deepseek-ai/dsh-client-ui-primitives, …). Anything else is bundled at build time.
  • cloudflared — found on PATH, at a common install location, or downloaded (SHA-256 verified) into $DSH_HOME/dsh-tunnel/bin.
  • A listening sshd, ideally key-only. If it is off, the panel prints the per-OS commands and prefills them in a terminal (see above); the bundle package README covers the same ground.

版本与发布记录

@zhangzhian/dsh-tunnel-core 共发布 6 个版本,首次发布于 2026/10/20;过去 12 个月发布了 6 个版本。

版本发布日期距今
0.3.1latest2026/11/03今天
0.3.02026/11/011 天前
0.2.22026/10/2113 天前
0.2.12026/10/2014 天前
0.2.02026/10/2014 天前
0.0.0-stage2026/10/2014 天前

关于 @zhangzhian/dsh-tunnel-core 的常见问题

@zhangzhian/dsh-tunnel-core 是什么?

dsh-tunnel的组件包:把本机sshd通过Cloudflare快速隧道暴露出去(主机半+设置页面板)

如何安装 @zhangzhian/dsh-tunnel-core?

在项目目录运行 npm install @zhangzhian/dsh-tunnel-core,或使用 pnpm add / yarn add / bun add。它还需要宿主项目提供 peer 依赖:@deepseek-ai/cordis(~4.0.4)、@deepseek-ai/schemastery(~3.18.4)、@deepseek-ai/dsh-api-gateway(^0.2.0-rc.2)、@deepseek-ai/dsh-client-locale(^0.2.0-rc.2)、@deepseek-ai/dsh-client-ui-slots(^0.2.0-rc.2)、@deepseek-ai/dsh-typert-protocol(^0.2.0-rc.2)、@deepseek-ai/dsh-client-ui-renderer(^0.2.0-rc.2)、@deepseek-ai/dsh-client-ui-settings(^0.2.0-rc.2)、@deepseek-ai/dsh-client-ui-primitives(^0.2.0-rc.2)、@deepseek-ai/dsh-api-terminal-controller(^0.2.0-rc.2)、@deepseek-ai/dsh-client-ui-sidebar-right(^0.2.0-rc.2)。npm 7 及以上与 pnpm 8 及以上默认会自动安装必需的 peer 依赖,Yarn 需要手动安装。

@zhangzhian/dsh-tunnel-core 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@zhangzhian/dsh-tunnel-core 支持 ESM 还是 CommonJS?

以 ES Module 形式发布,推荐使用 import 引入。在 CommonJS 项目中,Node.js 20.19+ / 22.12+ 可以直接 require() 不含顶层 await 的 ES Module,更早的版本需要改用动态 import()。

@zhangzhian/dsh-tunnel-core 可以商用吗?

@zhangzhian/dsh-tunnel-core 使用 MIT 许可。宽松许可:允许商业使用、修改和再分发,通常只需在分发时保留原版权与许可声明。以上为概括,不构成法律意见,请以许可原文为准。

@zhangzhian/dsh-tunnel-core 还在维护吗?

最新版本 0.3.1 发布于 2026/11/03(今天);至今共发布 6 个版本,其中过去 12 个月发布了 6 个;首次发布于 2026/10/20。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。