一个跨平台桌面应用,用来管理 SSH 本地端口转发(ssh -L 隧道)。把那些又长又难记的 ssh -L 3306:db.internal:3306 user@jump 命令存成一条条隧道,点一下就连,状态一眼可见,不用再在终端里手敲和盯着窗口。
基于 Tauri 2 + React + Rust(russh)实现,原生小体积,无需本地装 ssh 客户端。
平时连内网数据库、Redis、内部服务,常常要先开一条 SSH 跳板隧道。痛点:
- 命令长、参数多,记不住也容易敲错;
- 终端窗口一关隧道就断,得一直留着;
- 同时开好几条,分不清哪条通哪条断;
- 断线后要手动重连。
sshmgmt 把这些隧道集中管理:
- 粘贴即用:直接粘贴一条
ssh -L ...命令,自动解析成隧道配置。 - 一键连接 / 断开 / 重连,每条隧道一个状态灯(🟢 已连接 / 🟠 连接中 / ⚪ 未连接 / 🔴 失败)。断开按钮在「连接中」黄灯阶段同样立即生效,不会卡死。
- 自动重连:断线按退避策略自动重试;跳板机连不上时最多 15 秒判定超时,不会无限黄灯。
- 支持密码登录:跳板机没配好公钥免密也能连——弹窗输入用户名密码即可(同时兼容仅开放
keyboard-interactive的服务器,如企业 AD/Kerberos 环境)。密码可选择存入系统钥匙串,下次自动填充。 - 连接后自动上传公钥:密码登录成功后,勾选「连接后上传公钥」即可把本机公钥追加到服务器
authorized_keys,下次自动免密连接。 - 二级目标主机登录校验:如果某条转发的目标是另一台机器的 SSH 端口(如
-L 10010:10.125.162.245:22,通常是为了转发过去后再跳一次),连接时会顺带校验这台目标机的登录是否可行——优先尝试公钥(记住的用户名或从跳板机用户名推导),失败再弹密码框;只有两跳都验证通过才会显示绿灯。 - 存活探测:启动时自动探测本机端口,识别已经建立的隧道——无论是本应用建的,还是你在别的终端里手动
ssh -L起的,都会如实显示为已连接。 - 接管外部隧道:你手动开的隧道一旦断掉,应用可自动接手重建,端口无缝衔接。
- 分组 / 环境标签:按项目、按 dev/staging/prod 归类。
- 托盘常驻:最小化到系统托盘后台保活,隧道不断。
- 错误气泡不错过:连接失败、认证失败、保存失败等错误会弹出常驻提示条,必须手动点 ✕ 才会消失;成功类提示则几秒后自动消失,多条可堆叠、互不覆盖。
🔑 首次连接如果跳板机 / 目标机还没配好公钥免密,会弹窗要求输入用户名密码;密码可选择记住,也可选择连接成功后自动把本机公钥上传上去,下次就不用再输了。
到 Releases 下载对应平台的包:
| 平台 | 下载 |
|---|---|
| macOS(Apple Silicon,M 系列) | sshmgmt_x.y.z_aarch64.dmg |
| macOS(Intel) | sshmgmt_x.y.z_x64.dmg |
| Windows | sshmgmt_x.y.z_x64-setup.exe / .msi |
| Linux | .AppImage 或 .deb |
不确定 Mac 芯片?终端执行 uname -m:arm64 选 aarch64,x86_64 选 Intel 包。
这不是包真的损坏。因为本应用尚未做 Apple 代码签名 / 公证,macOS Gatekeeper 会给下载的文件打上「隔离」标记并拦截未签名应用,从而误报「已损坏」。
解决(把 app 拖进「应用程序」后,终端执行一次即可):
xattr -dr com.apple.quarantine /Applications/sshmgmt.app然后正常双击打开。之后不会再提示。
想彻底免除此提示,需要 Apple 开发者证书($99/年)对应用签名并公证。在那之前,请用上面的命令绕过。
- 新增隧道:点右上角「+ 新增隧道」,把一条完整的 ssh 命令粘进去,例如
应用会解析出监听端口、目标、跳板机等信息。可再填项目名、环境标签。
ssh -L 3306:db.internal:3306 -i ~/.ssh/id_ed25519 deploy@jump.example.com - 连接:在列表对应行点「连接」,状态灯转绿即已通。若跳板机(或二级目标主机)需要密码,会弹窗要求输入;点「取消」会直接放弃本次连接并断开,而不是留着一个卡在黄灯的僵尸连接。
- 断开 / 重连:用对应按钮;黄灯「连接中」阶段点断开同样立即生效;右上角「🔄 全部重连」适合切换网络 / VPN 后批量重连。
- 后台保活:点最小化会隐藏到系统托盘,隧道保持连接;点托盘图标可重新唤出窗口;托盘右键菜单可「全部重连」或「退出」。
- 已存在的隧道:如果某个端口已被你在终端里手动开的隧道占用,应用会自动识别并显示为已连接,不会冲突。
- 错误提示:任何操作失败(连接、保存、删除、密码认证失败等)都会在顶部弹出红色常驻提示条,需手动点 ✕ 关闭,确保不会错过;成功类提示几秒后自动消失。
- 最小化 / 失焦 → 隐藏到托盘,隧道继续运行。
- 托盘「退出」/ 关闭窗口 / Cmd+Q → 进程结束,应用内建立的隧道一并关闭(在别的终端手动开的隧道不受影响)。
需要 Node.js、Rust 和 Tauri 环境依赖。
npm install # 装前端依赖
npm run tauri dev # 开发模式(热重载)
npm run tauri build # 出当前平台的安装包,产物在 src-tauri/target/release/bundle/发布:改 package.json、src-tauri/Cargo.toml、src-tauri/tauri.conf.json 三处 version,提交后打 tag 推送:
git tag v1.1.0 && git push origin v1.1.0GitHub Actions(.github/workflows/release.yml)会自动在 macOS / Windows / Linux 上构建并把安装包传到一个草稿 Release,确认后点 Publish 即可对外下载。
- 前端:React 19 + TypeScript + Vite
- 后端:Rust + Tokio + russh(纯 Rust SSH 实现,无需系统 ssh)
- 框架:Tauri 2
- 密码 / 记住的目标主机用户名保存在系统钥匙串(Keychain / Credential Manager)。
每次连接,跳板机认证分两阶段、各用独立的 SSH 连接:先只尝试本地私钥(~/.ssh/id_ed25519 等),失败后换一条全新连接再走密码 / keyboard-interactive。这样即使服务器 MaxAuthTries 很低,公钥重试也不会把密码认证的机会提前耗尽。目标是 :22 的转发同理,先尝试公钥(记住的用户名或从跳板机用户名推导),再退回密码提示。整个建连+认证过程可被「断开」随时打断,不会卡在黄灯。
见 LICENSE。