dsh-web-ui/packages/dsh-ssh

5.1kStar311Fork49Issue5Watching

为 dsh Web GUI 添加 SSH 主机管理、命令执行、Web 终端、SFTP 文件传输、本地端口转发、集群并发执行与 6 个 Agent 工具,主机配置集中存于本机。

机审证据安装命令仓库已核验dsh-plugin Topic许可证READMEAI 百科

此插件是大仓库 zhu1090093659/dsh-web-ui 的子包,星数与活跃度统计的是整个仓库。

语言
TypeScript
License
Apache-2.0
分支
dev
deepseek-harnessdshdsh-pluginweb-ui

安装

$ dsh plugin --profile web add github:zhu1090093659/dsh-web-ui/packages/dsh-ssh

在终端中运行以上命令,通过 dsh CLI 安装此插件。可在右上角切换 Profile。 第一次用 dsh?看这篇新手教程

对话式安装

帮我安装 DeepSeek Harness 插件 zhu1090093659/dsh-web-ui/packages/dsh-ssh:先查看仓库 https://github.com/zhu1090093659/dsh-web-ui.git 确认安全性,然后执行安装命令并验证插件加载成功。

把这段指令粘贴给 DSH Web GUI 里的助手,由它代你完成安装与验证。

一句话定位

为 dsh Web GUI 加入一套完整的 SSH 运维能力:在 Web 端集中管理多台远程主机(增删改查、搜索、连接测试、一键导入 ~/.ssh/config),在 host 进程内复用持久 ssh2 连接池执行命令、跑 Web 终端、SFTP 传文件、开本地端口转发隧道,并在多台主机上并发跑同一条命令;同时为 Agent 提供 6 个工具调用同一份主机配置。

核心能力

  • 主机增删改查、搜索、连接测试;支持按环境/标签分组折叠与组内批量测试,支持密钥/密码认证、passphrase 密钥、ProxyJump 多级跳板机
  • 一键导入 ~/.ssh/config:解析 Host/HostName/User/Port/IdentityFile/ProxyJump 等字段,已有别名自动跳过(通配模式 / 缺 HostName 跳过)
  • 持久 ssh2 连接池:每台主机复用一条长连接(不每次重连),空闲 30 分钟自动断开,断线自动重连(最多 3 次)
  • 命令执行:单主机 exec 带超时(默认 60s,可覆盖)、stdout/stderr 分离、单次输出上限 2MB 截断保护
  • Web 终端(xterm.js + WebSocket PTY,背压自动暂停/恢复)、SFTP 文件传输(上传走 NDJSON 进度流,下载返回二进制流)、本地端口转发隧道(仅 127.0.0.1 监听,访问远程数据库/内网服务)、集群并发执行(默认并发 8,可按 alias/环境/标签过滤)
  • Agent 工具 ssh_list / ssh_exec / ssh_upload / ssh_download / ssh_tunnel / ssh_cluster,GUI 与 Agent 共享同一份主机配置

技术实现

  • 语言: TypeScript(host 半区 src/index.ts)+ TypeScript + React 18 + CSS Modules(browser 半区 src/client/
  • 关键依赖: ssh2 ^1.17.0(持久 ssh2 连接池 + SFTP)、@xterm/xterm ^6.0.0 + @xterm/addon-fit ^0.11.0(浏览器终端)、ws ^8.18.0(WebSocket PTY)
  • 架构模式: 双半区 cordis bundle。src/index.ts 是 host 半区(SshEngine 连接池 + /api/dsh-ssh/* 路由 + 6 个 Agent 工具 + 系统提示词宣告),src/client/index.ts 是 browser 半区(侧边栏入口 + 主机管理/终端/传输/隧道面板 + locale 注册)。bundle 声明在 packages/dsh-ssh/cordis.patch.yml:10-12(插入 id ssh),浏览器端通过 dsh.client.inject 注入 3 个官方 @deepseek-ai/dsh-client-*client-runtime / client-connection / client-ui-settings)+ platform: web。连接池默认参数:空闲 30 分钟、握手 15s 超时、keepalive 15s 间隔、输出 2MB 上限、集群并发 8、SFTP 并发 8(packages/dsh-ssh/src/engine/connection-pool.ts:30-38
  • 入口文件: packages/dsh-ssh/src/index.ts(host apply,applyImpl)、packages/dsh-ssh/src/client/index.ts(browser apply,apply(ctx));bundle 声明 packages/dsh-ssh/cordis.patch.yml:1-12,浏览器依赖 packages/dsh-ssh/package.json:32-40

适用场景

  • 日常需要同时管理多台 SSH 服务器(开发/测试/生产混合)的开发者:希望在 dsh Web GUI 中集中浏览主机、执行命令、传文件、开隧道访问远程数据库/内网服务,省去切换多个工具;
  • 想让 Agent 直接执行远程运维任务的开发者:在 GUI 中预先配置好主机(手动填或导入 ~/.ssh/config),Agent 就能通过 ssh_list / ssh_exec / ssh_upload / ssh_download / ssh_tunnel / ssh_cluster 调用同一套主机配置;
  • 已有 ~/.ssh/config 的用户:通过「导入 ssh_config」一键把所有现成的 SSH 别名同步到插件,无需重复输入 host/port/user/identityFile。

前置依赖与兼容性

依赖最低版本说明
DSH 宿主0.1.0-rc.8+ 推荐package.json 未在 dsh.engines 声明;devDependencies 统一锁到 @deepseek-ai/dsh-* ^0.1.0-rc.8
Node.js^22.19.0>=24.0.0package.json engines.node
平台跨平台host 半区跑 Node.js、client 半区跑浏览器;ssh2 是纯 JS 库,无 OS 限制
原生模块无(运行时)ssh2 不需要 native 绑定;上传/下载走 ssh2 自带 SFTP
React^18.2.0peerDependency,由宿主运行时注入
SSH 服务端任意标准 OpenSSHhost 半区作为 ssh2 客户端,不依赖服务端版本

安装方式

dsh plugin --profile web add github:zhu1090093659/dsh-web-ui/packages/dsh-ssh

配置项

本插件在 dsh 设置面板的「SSH」区域提供 3 个开关/输入:

配置类型说明默认值
enabled开关插件总开关;关闭后不注册 /api/dsh-ssh/* 路由、不注册 Agent 工具、不向 Agent 宣告true
announceToAgent开关是否在系统提示词中向 Agent 宣告本插件(关闭后 Agent 看不到 SSH 工具)true
terminalFontFamily字符串Web 终端字体(写入 xterm fontFamily);留空走 CSS 链(--dsh-ssh-terminal-font → 官方 --ds-font-family-code token → 内置 monospace 栈)。要渲染 powerline / Nerd Font 图标请填 Nerd Font 栈(如 "SauceCodePro Nerd Font", monospace)。对已打开的终端实时生效""

引擎内部还有几处不暴露给 GUI 的硬编码常量(packages/dsh-ssh/src/engine/connection-pool.ts:30-38):空闲超时 30 分钟、握手超时 15 秒、keepalive 间隔 15 秒、输出上限 2MB、exec 默认超时 60 秒、集群默认并发 8、SFTP 并发 8;上传单次请求体上限 4 GiB(packages/dsh-ssh/src/routes.ts:27-28)。调整需改源码后重新构建。

常见问题

Q: 安装之后侧边栏没出现 SSH 入口怎么办?

A: 重启 dsh web。bundle 激活是 host 启动时一次性做的,刷新浏览器不足以触发。重启后侧边栏出现「SSH」入口;Agent 提示词也会自动带上插件说明(受 announceToAgent 开关控制)。重启流程见 packages/dsh-ssh/README.zh.md:47packages/dsh-ssh/README.md:47

Q: 密码是怎么保存的?安全吗?

A: 密码 / passphrase 以明文存于 ~/.dsh/dsh-ssh.json,文件权限 0600、目录 0700,原子写入(tmp + rename)。这是与 ssh-skill 同一信任模型——既然 ~/.ssh/config 也常以注释形式存密码,本插件不做额外加密(避免密钥管理带来新风险)。文件路径与权限在 packages/dsh-ssh/src/store.ts:18-20、347-355

Q: 局域网里别人能访问我的 SSH 控制台吗?

A: 不能。所有 /api/dsh-ssh/* 路由仅信任本机回环连接(socket 地址必须命中 IPv4 127/8 / ::1 / IPv4-mapped ::ffff:127/8,并要求同源 Host header + sec-fetch-site / Origin 校验),LAN 邻居直接 403。WebSocket 终端升级也走同一个 loopback 围栏;本地端口转发隧道只监听 127.0.0.1,不会暴露到 LAN。详见 packages/dsh-ssh/src/routes.ts:101-111packages/dsh-ssh/src/loopback.ts:44-62

Q: Agent 能在我没配置的主机上执行命令吗?

A: 不能。Agent 只能操作 GUI 中已配置、或从 ~/.ssh/config 导入的主机别名。如果别名未配置,ssh_exec / ssh_upload 等工具调用会直接报错,不会臆造主机。这一约定同时写在系统提示词「限制」段(packages/dsh-ssh/src/index.ts:67)与 packages/dsh-ssh/README.md:27

Q: 远程输出会脱敏吗?比如 env 这种命令?

A: 不会。exec / cluster 的 stdout/stderr 原样返回(不做 secret 替换),env 这类命令可能把远端环境变量里的密钥带回对话记录。这是 ssh-skill 同样的语义——传输 / 执行消耗真实远程资源、Agent 使用前需用户确认。语义在 packages/dsh-ssh/src/index.ts:67packages/dsh-ssh/README.md:29

Q: 下载文件怎么操作?能不能下载整个目录?

A: GUI 与 ssh_download 工具都只能下载单文件:先在「传输」面板的远程文件浏览器里挑文件,再走 /api/dsh-ssh/download(返回二进制流,浏览器保存)。上传支持本地目录递归(walk 后逐文件传);下载暂不支持整目录批量。限制见 packages/dsh-ssh/README.md:69packages/dsh-ssh/src/tools.ts:194-198

Q: 跳板机能用 ~/.ssh/config 里的别名吗?

A: 不能。ProxyJump 链上的每一跳必须是本插件已配置的主机别名(不能跨插件引用 ~/.ssh/config 里的别名);导入时若某跳不在本插件主机表中,会在创建时报错跳过。限制见 packages/dsh-ssh/README.md:71packages/dsh-ssh/src/protocol.ts:30-32

Q: 自动重连会不会重放我的命令?

A: 会。exec 在断线时会自动重连(keepaliveCountMax=3),连接重置后命令会重新发送;非幂等命令(如 rm、追加写文件)会有副作用,请优先用幂等命令或预先确认。详见 packages/dsh-ssh/src/engine/connection-pool.ts:72packages/dsh-ssh/README.md:70

上手难度

入门 — 一行命令安装、重启 dsh web 即可见 SSH 入口;主机可在 GUI 里手动填或一键导入 ~/.ssh/config,无需写配置文件或命令行。但因涉及远程主机、密钥、跳板机,建议先试一两条 exec / 隧道再批量使用。

已知问题与限制

  • 上传的远程目标路径必须为绝对路径,相对路径会被拒绝(packages/dsh-ssh/README.md:68packages/dsh-ssh/src/tools.ts:158-162
  • 下载仅支持单文件;上传支持本地目录递归(walk 后逐文件传),下载整目录未实现(packages/dsh-ssh/README.md:69
  • exec 断线自动重连(keepaliveCountMax=3)会重发同一命令,非幂等命令需自行注意副作用(packages/dsh-ssh/src/engine/connection-pool.ts:72packages/dsh-ssh/README.md:70
  • ProxyJump 链上的每一跳必须是本插件已配置的主机别名,不能跨插件引用 ~/.ssh/config 别名(packages/dsh-ssh/README.md:71
  • 断点续传(resume)暂未实现;单次上传请求体上限 4 GiB(packages/dsh-ssh/src/routes.ts:27-28
  • Agent 工具的传输路径是宿主机器本地路径(与 ssh-skill 同一语义)——ssh_upload / ssh_download 以宿主进程权限直接读写本机任意路径,不经 bash 沙箱,请注意该权限面(packages/dsh-ssh/README.md:28packages/dsh-ssh/src/index.ts:67
  • 主机配置 ~/.dsh/dsh-ssh.json 以明文保存密码与 passphrase,文件 0600、目录 0700,不做加密(packages/dsh-ssh/src/store.ts:347-355packages/dsh-ssh/README.md:24
  • exec / cluster 远程输出原样返回(不脱敏),env 等命令可能带回远端环境密钥(packages/dsh-ssh/src/index.ts:67packages/dsh-ssh/README.md:29
  • 本地端口转发隧道只监听 127.0.0.1,外部网络无法访问;这是围栏设计而非可配置项(packages/dsh-ssh/src/loopback.ts:44-62
  • 主机别名仅允许字母、数字、点 .、连字符 -、下划线 _(首字符不能是分隔符);不符合的正则会在创建/导入时报错跳过(packages/dsh-ssh/src/store.ts:62-68、296-303
  • 配置文件损坏时会被重命名为 .corrupt-<timestamp> 备份、随后启动为空表,不会被静默覆盖(packages/dsh-ssh/src/store.ts:334-342

收录徽章

Listed on deepseek-plugin.org
[![Listed on deepseek-plugin.org](https://img.shields.io/badge/listed_on-deepseek--plugin.org-007EC6)](https://deepseek-plugin.org/plugins/zhu1090093659/dsh-web-ui/packages/dsh-ssh)

把这段 markdown 粘贴到你的 GitHub README,链接回本插件详情页。徽章只声明已被本站收录,不代表安全认证。

返回插件目录