dsh-ssh-remote-tunnel
DeepSeek Harness (DSH) 插件:把远程服务器上的 OpenAI 兼容模型(默认配置为 Qwen vLLM)通过 SSH 端口转发隧道拉回本机,并注册为 DSH 中可选择的 provider / 子代理模型。无需 PuTTY/plink——只要机器上有任意能建立 SSH 连接的客户端(Windows 自带 OpenSSH ssh 即可)就能用。
v0.3.0 变更:
- 更名为
dsh-ssh-remote-tunnel(SSH 转发隧道)。 - 去 plink 依赖:新增
sshClient选项(auto/ssh/plink),默认auto优先使用 OpenSSHssh。 - 无 plink 也能密码登录:OpenSSH 密码认证通过
SSH_ASKPASS(Windows)/sshpass(Linux/macOS)自动注入,免交互;不填密码则走密钥认证(BatchMode)。 - 设置页新增「SSH 客户端」下拉、「ssh 路径」字段与「检测 SSH」按钮;状态区显示所用客户端与认证方式。
- 保留 plink 作为可选客户端(
sshClient: plink或auto下无 ssh 有 plink 时自动启用)。
它做了什么
| 时机 | 行为 |
|---|---|
| DSH 启动 | ping 服务器(ICMP + TCP/sshPort 双探测),连通后才继续 |
| 连通后 | 选择 SSH 客户端并建立 localPort → remoteHost:remotePort 本地转发。默认 OpenSSH ssh:有密码走 SSH_ASKPASS/sshpass 自动登录,无密码走密钥(BatchMode=yes) |
| 隧道就绪 | 轮询 http://localhost:localPort/v1/models,列出模型,做一次 1-token 推理探针 |
| 模型注册 | 把端点写进 llm-pi-ai 设置段(provider 默认 qwen,模型由 models 配置决定),出现在模型选择器中,可用于子代理 |
| 隧道断线 | 健康检查发现本地端口关闭则自动重启(最多 maxTunnelRestarts 次) |
| DSH 终止 | 杀掉隧道进程、清理密码临时文件,移除本插件注册的 provider 路由 |
SSH 客户端选择(无需 plink)
config.sshClient(设置页「SSH 客户端」下拉,默认 auto):
| 值 | 行为 |
|---|---|
auto(默认) |
优先 OpenSSH ssh(不需要 plink);仅当机器上没有 ssh 但有 plink 时才用 plink |
ssh |
强制 OpenSSH。密码 → SSH_ASKPASS(Win) / sshpass(Linux/macOS) 自动注入;无密码 → 密钥认证 |
plink |
强制 PuTTY plink.exe(-pw 自动密码,-batch 免交互) |
- Windows:系统自带 OpenSSH(
C:\Windows\System32\OpenSSH\ssh.exe),留空即可自动找到。密码登录时插件在临时目录生成一个askpass.bat由 OpenSSH 的SSH_ASKPASS读取,隧道停止/重启时自动删除。 - Linux / macOS:密码登录需要
sshpass(apt install sshpass/brew install hudochenkov/sshpass/sshpass);没有 sshpass 时密码登录不可用,可改用密钥认证或安装 plink。 - 路径解析:
sshPath/plinkPath留空时分别从 PATH 及系统常见目录自动查找;填目录会追加对应可执行文件名。
DSH Desktop 设置子页面
在 DSH Desktop 的设置侧边栏中新增「SSH 隧道」页面,包含三组:
- 远端配置 — 可编辑字段:远端 IP / SSH 端口 / SSH 用户 / SSH 密码 / 本地端口 / 远端转发目标 / 远端 vLLM 端口 / SSH 客户端(auto/ssh/plink)/ ssh 路径 / plink.exe 路径 / 主机密钥指纹。
- 隧道状态 — 实时显示当前阶段、所用 SSH 客户端(+路径)、认证方式(密码/密钥)、API 就绪、provider 注册状态、模型列表、重启次数、PID、最后错误。
- 操作 — 保存配置 / 启动隧道 / 停止隧道 / 检测 SSH / 检测 plink 五个按钮。
页面通过宿主注册的 HTTP 端点(/plugins/ssh-remote-tunnel/*)通信,每 3 秒自动轮询状态。
安装
从插件市场
上架入口见文末「上架到插件市场」。安装命令(上架后):
dsh plugin --profile web add dsh-ssh-remote-tunnel
从源码 / 本地链接
本机约定:所有 DSH 插件本体统一放在
D:\Tools\dsh_plugins\<插件名>,其他位置一律通过符号链接(pnpm add link:)引用。
- 插件本体:
D:\Tools\dsh_plugins\dsh-ssh-remote-tunnel - 启用(以 web profile 为例):
- 在 profile 目录下
pnpm add link:D:/Tools/dsh_plugins/dsh-ssh-remote-tunnel - 在
dsh.profile.bundles数组中加入"dsh-ssh-remote-tunnel"(web/desktop 需要客户端半部;headless 不需要) - 本包的
cordis.patch.yml(bundle patch)会自动插入id: ssh-remote-tunnel行;若某 profile 在别处又写了同 id 的insert,会因 loader entry id 重复导致 Desktop 无法打开——只保留一处insert,其余用id-targetedconfig覆盖。
- 在 profile 目录下
若从旧的
dsh-qwen-tunnel迁移:旧插件行 id 为qwen-tunnel,新插件为ssh-remote-tunnel,二者不会冲突;请移除旧插件并改用新 id。旧的持久化配置文件.dsh-qwen-tunnel.json不再读取(新文件为.dsh-ssh-remote-tunnel.json)。
配置
方式一:通过 DSH Desktop 设置页面(推荐)
- 打开 DSH Desktop → 左下角「设置」→「SSH 隧道」
- 填写远端 IP / 端口 / 用户 / 密码 / 客户端
- 点击「保存配置」→「启动隧道」
方式二:通过 cordis.patch.yml(headless / 持久化)
- insert:
- id: ssh-remote-tunnel
name: dsh-ssh-remote-tunnel
config:
host: 10.0.0.1 # SSH 服务器(替换为你的 IP)
sshPort: 22 # SSH 端口
sshUser: youruser # SSH 用户
password: 'yourpassword' # 自动登录密码(字符串,注意加引号)
localPort: 16324 # 本地监听端口
remoteHost: localhost # 远端转发目标
remotePort: 8000 # 远端 vLLM 端口
sshClient: auto # auto | ssh | plink(默认 auto,优先 OpenSSH,无需 plink)
# sshPath: 'C:\\Windows\\System32\\OpenSSH\\ssh.exe' # 留空则自动查找
# plinkPath: 'C:\\Program Files\\PuTTY\\plink.exe' # 仅 plink 客户端需要
hostKeyFingerprint: 'ssh-ed25519 255 SHA256:xxxx' # 主机密钥指纹(可选)
apiBaseUrl: http://localhost:16324/v1
providerKey: qwen # 模型选择器里显示的 provider 名(可改为任意,如 ssh-vllm)
displayName: 'Qwen vLLM (SSH Tunnel)'
models: # 注册进模型选择器的模型
- id: /model
name: 'Qwen3.8 vLLM'
- id: qwen3.8-27b-fp8
name: 'Qwen3.8 27B FP8 (vLLM)'
registerProvider: true
- 不想把密码写进配置文件时,删掉
password字段并设置环境变量QWEN_SSH_PASSWORD(或配置passwordEnv: 其他变量名);不填密码则走密钥认证。 - 密码登录且
sshClient: auto/ssh时,需要本机存在密码注入手段(Windows 用系统 OpenSSH 的SSH_ASKPASS,Linux/macOS 需sshpass)。若都不可用且未装 plink,插件会明确报错提示。
把 Qwen 用作子代理模型
注册成功后(重启 DSH 生效),模型选择器里会出现 provider qwen(或你设置的 providerKey)的模型,新会话/子代理可直接选用。默认模型未被改动。
如需让某个子代理工具固定用它,在 cordis.patch.yml 追加(示例):
- insert:
- id: tool-subagent-ssh-vllm
name: '@deepseek-ai/dsh-tool-subagent'
config:
provider: spawn
toolName: subagent_ssh_vllm
agentOptions:
provider: qwen
model: /model
验证
无需重启即可独立验证隧道链路:
$env:QWEN_TEST_PASSWORD = '<ssh 密码>'
node test/smoke.mjs # 在插件目录下运行;覆盖 ping、ssh 隧道(SSH_ASKPASS)、API、模型、推理探针、清理
node test/provider-shape.mjs # 纯离线,校验 provider profile 形状
注意
- 密码以明文存于本机
cordis.patch.yml(与桌面.bat相同的信息暴露级别)。设置页/进程内存中的密码不落盘;OpenSSH 密码登录的临时askpass.bat仅在隧道运行期间存在于系统临时目录,停止即删除。 - 若 DSH 被强制杀掉(进程级 kill),清理逻辑不会运行;下次启动时插件会自动释放旧
ssh/plink占用的本地端口,并清理残留的 askpass 临时文件。 - 若你在 Models 页面手动改动了该 provider,插件终止时不会覆盖/删除你的配置。
- 设置子页面仅在 DSH Desktop(web/desktop profile)中可用;headless 模式仅支持
cordis.patch.yml配置。 - 本插件只做 SSH 本地端口转发与模型端点注册,不代理任意流量;隧道端口仅监听
127.0.0.1。
上架到插件市场
DSH 的「插件市场」(dshmarket)不接收直接上传——它的目录来自精选列表 awesome-dsh-plugin(站点 awesome-dsh-plugin.com,每次打开实时拉取 plugins.json)。上架步骤:
- 创建公开 GitHub 仓库(如
<你的账号>/dsh-ssh-remote-tunnel),把本插件代码推上去(package.json的repository指向该仓库)。截图与来源追溯都来自该仓库。 - 发布 npm 包(可选但推荐,安装即走 npm tarball,秒级):
若只走 GitHub 分发,把仓库设为 public 即可,市场会用npm login npm publish --access publicgithub:源安装。 - 向 awesome-dsh-plugin 提 PR:在列表里加一条,字段参照
plugins.json的结构——
站点与市场会自动收录,通常一天内生效。分类建议{ "name": "dsh-ssh-remote-tunnel", "owner": "Cumeskey", "url": "https://github.com/Cumeskey/dsh-ssh-remote-tunnel", "category": "remote", "description": { "en": "Automatic SSH port-forward tunnel to a remote LLM/vLLM server (OpenAI-compatible). Plink-free: works with any SSH client (OpenSSH ssh with password via SSH_ASKPASS/sshpass, or key auth). Registers the tunneled model as a DSH provider for subagent selection.", "zh": "SSH 端口转发隧道,把远程 LLM/vLLM(OpenAI 兼容)拉回本机并注册为 DSH provider。无需 plink:任意 SSH 客户端即可(OpenSSH ssh 密码登录走 SSH_ASKPASS/sshpass,或密钥认证)。" }, "npm": "dsh-ssh-remote-tunnel" }remote(Remote & Mobile)或model(Models & Providers)。注意:市场安全策略只允许安装 awesome-dsh-plugin 精选列表内的来源,所以必须走这条 PR,不能往 dshmarket 仓库直接提条目。
许可
MIT
No comments yet. Be the first to write one.