ssh-net
v26.10.43
Published
个人 SSH 组网:v6 直连优先、relay 兜底、关机有界重试后静默
Maintainers
Readme
ssh-net
个人 SSH 组网:把散在不同网络里的五台机器,用原生 ssh 隧道拼成一张「互相可达」的网。 单用户、只给自己用。
它解决什么
在公司 edge(MacBook)── 局域网原生直连 ──► core / node
在家 edge ── 公网 IPv6 一条 ssh(peer)──► core
edge ── ProxyJump relay ─────────► core / node
兜底/咖啡厅 直连没建立或只有 v4 时,全部自动走 relay- edge:两台 MacBook(人在的一端,有公网 v6,经常关机)
- core:一台 Mac mini(7×24 常驻办公室,内网锚点与 SOCKS 出口)
- node:两台 Linux devbox(只走 relay 兜底)
- relay:一台公网 VPS(只跑标准 sshd,不装 ssh-net)
关机/合盖后 core 的回拨作业最多两拨:ssh 退出后 5s 再拨一次,第二次仍 退出即 disable 休眠、彻底静默(作业保留不删,跨重启不复发);开盖后从 edge 发起第一条 ssh 时,选路脚本现场经中继通知 core 回拨(6 秒硬预算: 回拨及时就走直连,否则本次走中继、回拨已在路上,下一条即直连),无需 手动操作。
设计原则
- edge 默认零常驻:选路不依赖常驻服务——发起 ssh 时 Match exec 的
sn-route 现场判决(先探环回口 banner,不通就经中继按需通知回拨,6 秒
预算),没有心跳、TTL、janitor、消息队列;只有要 SOCKS/VNC 本地转发口
才
ssh-net install --with-link加装一个纯 ssh 透传常驻作业(它不判决、 不报名,只持有转发) - 常驻进程只有套着薄脚本的原生 ssh(core/node 与 edge 的 link 附加件):
npm 包内每类一个 bash 脚本,install 对账进
~/.ssh/ssh-net/bin(原名实体 + 带机器名软链,差异只走参数)——在线状态就是 TCP 会话本身 - 控制面与运行时分离:控制面是 Node 24+ 的 mjs(install/start/status/RPC);
运行时是纯 bash 脚本 + ssh 的实体拷贝,零 npm/fnm/node 依赖——npm 误
卸载、fnm 切版本不影响常驻服务;包升级
npm i -g后重跑 install 刷新, runtime-version 戳由 status 对账 - npm 包分发:消费机
npm i -g ssh-net,不 clone;个人配置全部在 dotfiles 托管(~/.ssh/ssh-net/topology与 ssh config 的静态 Host 块),包内零个人数据; 选路 Match、VS Code 连接打标与 core 上的 edge 入口由 install/报名渲染进~/.ssh/ssh-net/conf.d/(生成物,ssh config 一行 Include 接入)
edge 的两个开关与 link 附加件
隧道意图拆成两个开关(~/.ssh/ssh-net/state/ 空标记,存在=开):
| 开关 | 管什么 | 依赖 |
| --- | --- | --- |
| relay(根) | 出站中继线路、报名信道;link 附加件的作业也盯它生死 | —— |
| peer | 允许选路脚本按需报名 v6(经中继告诉 core 回拨进来)、接受 core 回拨 | 需要 relay |
转发口(SOCKS/VNC)不再是开关,而是装不装附加件:
- 默认
ssh-net install:零常驻进程,只装选路/信令/探测脚本;发起 ssh 时按需确保直连 ssh-net install --with-link:加装一个纯 ssh 透传作业,持有本地 SOCKS/VNC 转发口;--without-link移除
ssh-net start / stop 缺省全开/全关;start peer、stop peer 细粒度
(start peer 顺带把 relay 补上,并立即报名一次)。只要被连接、不要转发口,
默认形态就是全部。人在 edge 上想立即被连上:ssh-net start peer
(立即报名,core 无条件重拨)。
选路与进度:ssh <core> 时 Match exec 先试环回口直连(旧回拨活着约 10ms
命中);不通且 peer 开着,就经中继通知回拨并等待(6 秒预算),终端里能
看到「正在尝试直连 → 通知回拨 → 回拨成功,走直连/经中继连接」的进度。
回拨建立时 edge 本地会弹一次桌面通知「与 <core> 的直连已就绪」
(terminal-notifier 优先,装了 brew install terminal-notifier 图标和
点击体验更好;没装走系统自带 osascript,无需任何配置——VS Code、scp 等
没有终端进度的场景就靠这个通知),装了 link 附加件时同时把转发口秒切
到直连。
安装
需要 Node 24+(fnm 的 default 版本,非交互 ssh 经 ~/.zshenv 同样可用)。
npm install -g ssh-net源码安装(仅开发机):
git clone [email protected]:adaex/ssh-net.git ~/space/ssh-net
cd ~/space/ssh-net && npm link安装后在各角色机器上执行 ssh-net install。前提是 topology 已就位
(~/.ssh/ssh-net/topology,由个人 dotfiles 仓的 dot apply ssh 落盘——
缺它时任何命令都会拒绝并提示);装完跑 ssh-net status 确认各线路就绪。
edge 默认装成零常驻形态,需要本地 SOCKS/VNC 转发口再
ssh-net install --with-link(转发定义在 topology 里)。
升级:各机跑 ssh-net update(= npm i -g ssh-net@latest
--prefer-online 跳过缓存 dist-tags 后由新装的二进制跑 ssh-net install
刷新运行时;ETARGET 传播窗口自动重试一次)。node 机器上以 root 跑
(非交互 ssh 下 sudo 的 secure_path 不含 fnm,用登录 shell:
ssh n007 'sudo -i ssh-net update')。开发机(npm link 状态)不要用
update——重跑 ssh-net install 即可;发新版走 GitHub Release,由
Actions 跑测试后自动发布到 npm。
改名说明:该命令 26.10.42 起叫
update(原名upgrade)。旧版机器 跑一次ssh-net upgrade升到新版即可;26.10.25 之前的版本两个名字都 没有,先手动跑一次npm i -g ssh-net@latest --prefer-online && ssh-net install。
卸载顺序:先 ssh-net uninstall(移除 launchd/systemd 作业、运行时
脚本与状态),再 npm uninstall -g ssh-net;反过来会留下反复重启的注册作业。
开发
零依赖、零构建,要求 Node 24+:
node --test # 全部测试(纯模块 + shell 喂参 + 命令编排)
npm pack --dry-run # 发布前核对产物(脚本可执行位、files 清单)
npm link # 开发机:控制面改即时生效(运行时脚本仍靠 ssh-net install 拷贝落盘)发布物零真实拓扑数据:别名、主机名、环回注册端口只在私有文档与个人配置里,
测试 fixture 一律 RFC 5737(192.0.2.x)与 2001:db8:: 文档地址。
文档
| 文件 | 内容 | | --- | --- | | docs/design.md | 架构、角色、选路与回拨路径、组件详细设计、安全模型 | | docs/notes.md | 运维事实、参数依据、实测数据、被否方案 | | CHANGELOG.md | 发布记录(随包分发;当前版本与各版内容以它为准) |
状态
当前版本与各版内容见 CHANGELOG.md(版本号「年.月.序号」, 序号=累计发包数)。本页不维护版本摘要——此前手工同步停更过四次,改成单一来源。
