Electerm 连接跳跃:不用背 ProxyJump 的跳板机用法
数据库在 10.0.0.5,没有公网 IP,22 端口也不对外——唯一走法是 笔记本 → bastion.example.com → 10.0.0.5。原生 OpenSSH 要写 ProxyJump、拼 -J 参数、折腾 agent 转发,两遍密码还得按顺序输对。
electerm 把这条链做成书签上的有序列表:每跳填自己的 host、用户和凭证,最终目的地还是书签本身。看一眼上面的横幅——一个循环先连跳板机,再 forwardOut 穿过去,最后落在目标上。这篇文章讲的就是这个循环。
基础文档:Connection Hopping Behavior Change since v1.50.65。总览篇:Electerm SSH 全解。
30 秒心智模型
跳跃链就是嵌套的 SSH 连接。electerm 按你列的顺序一跳跳拨过去,每一跳都以前一跳为隧道(conn.forwardOut),shell 只开在最后一台上:
笔记本 ──SSH──► 跳板机 ──forwardOut──► 网关 ──forwardOut──► 10.0.0.5(shell 在这)
三句话扫清一大半困惑:
- 书签自己的 host 就是最终目的地——它不在跳跃列表里,列表只放中间节点。
- 列表是连接顺序,从上往下:第 1 行最先拨,最后一行紧挨目标。拖
⋮⋮手柄可排序。 - 列表底下有一行实时路径
👤 -> bastion -> gateway -> 10.0.0.5(connection-hopping.jsx里的renderPaths)。路径读着不对,顺序就是错的。
在 electerm 里哪里配跳跃
打开任意 SSH 书签 → 连接跳跃选项卡(config/ssh.js → connectionHoppingTab(),界面是 connection-hopping.jsx + connection-hopping-form.jsx):
- 填host(必填)、端口(默认
22)、用户名。 - 选认证方式填凭证——密码、私钥 + 可选 passphrase、证书,或已存的 profile。每跳独立认证。
- 捷径:从书签选择——挑一个现成书签,host/用户/认证自动填进表单(没存密码的自己补一下)。
- 点添加按钮。行里显示
user:*****@host:port (privateKey:*****),带铅笔改、减号删。 - 第 2 跳、第 3 跳照此添加……保存书签并连接。 electerm 先拨第 1 跳,再经第 1 跳拨第 2 跳,依此类推,最后穿过去连书签主机。终端、SFTP、SSH 隧道都跑在最终连接上。
改配置点铅笔(弹窗改),删除点减号,排序直接拖。一个书签可以挂任意多跳(bookmark-schemas.js 里 connectionHoppings 就是数组)。
进阶:quick-connect 连接串也能带跳跃,例如 ssh://user@10.0.0.5?opts={"connectionHoppings":[{"host":"bastion.example.com","port":22,"username":"jumper"}]}。
v1.50.65 顺序变更(只看这一次)
v1.50.65 起列表含义是连接顺序。引擎(session-ssh.js 里的 adjustConnectionOrder)拿第 1 行当第一次连接,把书签自己的 host/端口/用户/key 追加为最后一步:
// 你看到的:hops = [bastion, gateway],书签 host = 10.0.0.5
// 实际连接:bastion -> gateway -> 10.0.0.5
const [firstHopping, ...restHoppings] = initOptions.connectionHoppings
initOptions.connectionHoppings = [...restHoppings, currentHostHopping]
老版本语义是反的,所以老客户端建的书签会弹一次性警告条(ConnectionHoppingWarningText,hasOldConnectionHoppingBookmark),带 wiki 链接。看到它:读 wiki,把行拖成连接顺序,点"已读",一劳永逸。
笨办法:表格底下的
👤 -> …路径,必须跟你的ssh -J bastion,gateway target从左到右一个样。
1. 单跳:跳板机场景
**形状:**书签 host = 10.0.0.5(内网),跳跃 = [bastion.example.com]。
配置:
- 书签本身:host
10.0.0.5、端口22、用户名dbadmin,填 DB 那边的凭证。 - 第 1 跳:host
bastion.example.com、端口22、用户名jumper,填跳板机凭证。 - 路径行应该是
👤 -> bastion.example.com -> 10.0.0.5。
保存、连接。electerm 先 SSH 到跳板机,在上面调 conn.forwardOut('127.0.0.1', 0, '10.0.0.5', 22),下一次 SSH 握手就跑在这条流里(session-ssh.js 的 jump() / hopping())。CLI 对应:ssh -J jumper@bastion.example.com dbadmin@10.0.0.5。
视频:Electerm Connection Hop(老版 Electerm Connection Jump 录于顺序变更之前,行顺序是旧语义)。
2. 多跳链
从上往下按拨号顺序加行。例子——笔记本 → bastion → 10.0.0.9(网关)→ 10.0.0.5(db):
- 第 1 跳:
bastion.example.com - 第 2 跳:
10.0.0.9(站在跳板机角度能连到就行,内网地址没问题) - 书签 host:
10.0.0.5(站在 10.0.0.9 角度能连到就行)
每跳的 host:port 都是站在上一跳的网络里解析的,跟链式 ProxyJump 一模一样。所有跳跃连接都留在 this.conns 里,关掉标签页一起回收(endConns / kill(),不留僵尸跳板会话)。
跳数没有硬限制,一般两三跳最常见。再多就该想想 VPN、NetBird 路由或一条 SOCKS 隧道是不是更合适(见下)。
3. 每跳认证:agent、跳板机上的 key、密码
每跳独立认证,electerm 会尽量不弹框打扰你。单跳的尝试顺序(jumpConnect / retryJump / readPrivateKeyInJumpServer):
- 先试 SSH agent。 agent 转发语义覆盖整条链,electerm 默认就开(
useSshAgent,支持自定义sshAgent路径)。agent 能过,这一跳就不读 key 了。 - 试跳板机上的 key。 agent 不行、且该跳没配显式密码/key 时,electerm 列出当前跳板机
~/.ssh/*.pub并逐个试私钥(ls ~/.ssh+cat <key>)。key 要 passphrase 才弹框。 - 用行里存的密码 / key。 表单里存了啥先试啥,免弹框。
- 最后才弹框。
password for user@hop(或passphase for hop/keypath)出现在登录框里。纯 keyboard-interactive 的目标会自动填已存密码,不弹框(#4427,onKeyboardEvent的passwordOverride)。 - 每跳单独验 host key。 每台新跳板/新目标都走 known-hosts 确认(
createHostVerifier+getHostVerificationTarget),第一次 trust 一次,以后不再问。
实操建议:
- 天天用优先 agent:
ssh-agent/ 1Password / KeePassXC 里加一次 key,跳跃行保持无凭证。 - 无人值守书签(共用跳板账号)就把跳板密码或 key 存行里,或让行引用 profile。
- 跳跃行同样支持证书——跟主书签一样的
privateKey + certificate + passphrase三件套,按跳跃主机的 principal 匹配。
4. VNC / RDP 也能跳(还有 Spice)
跳跃不是 SSH 标签页专属。VNC、RDP、Spice 书签有同样的选项卡,实现不同(session-hop.js → createHopProxy):electerm 弹出最后一跳,开一个一次性 SSH 会话带动态 SOCKS 转发(loopback 随机空闲端口),桌面协议走 socks5://127.0.0.1:<端口> 过去。关掉桌面标签页,SSH 会话跟着杀掉。
所以 10.0.0.20:5900 的 VNC 藏在同一跳板机后面,写法一样:VNC 书签 host 10.0.0.20 + 跳跃行 bastion.example.com。心智模型不变,只是顺序照样从上往下。
5. 跳跃 vs 隧道 vs ProxyCommand vs NetBird
| 需求 | 用 | 为什么 |
|---|---|---|
| 到跳板机后的机器开 shell / SFTP | 跳跃(本篇) | 每跳独立认证,整个会话穿过去 |
| 只够一个端口(DB、管理后台),且那台机器本来就能 SSH | SSH 隧道(-L) |
不用多一次跳跃登录,见SSH 隧道 |
Mesh / SSO / 内网 DNS(NetBird、Tailscale 类、cloudflared、aws ssm) |
ProxyCommand / NetBird | 传输是命令的 stdio,不是跳跃登录,见 SSH 全解 |
已有复杂 ssh_config 的固定跳法 |
~/.ssh/config 写 ProxyJump + 普通书签 |
electerm 照样走 agent;跳跃 UI 更适合分享给团队 |
代码里的冷知识:书签带跳跃时跳过 proxy-command / NetBird 自动探测(maybeProxyCommandSock 直接返回),中间跳不配 X11——shell 通道只开在最后一台。
排错清单
- 第 2 跳之后"connection refused"——跳跃地址是站在上一跳解析的,不是你的笔记本。先 SSH 上第 1 跳,在里面连第 2 跳地址验证。
10.x内网名只配第 2 行之后。 - 顺序看着是反的——可能是 v1.50.65 之前的老书签。看
👤 -> …路径:必须是从先拨到后拨。拖行、确认警告。 - 某跳 "All configured authentication methods failed"——该跳行里没可用凭证 + agent 里没 key + 跳板机
~/.ssh也没 key。给行里补密码/key,或 agent 里加 key。纯 keyboard-interactive 目标记得把密码存书签上(自动填,#4427)。 - 密码框问的主机不对——跳跃弹框都带主机名
password for user@hop-host,看清再输;目标密码在书签上,跳跃密码在行里。 - shell 能上但穿跳失败——中间机要开
AllowTcpForwarding yes(多数发行版默认开)。跳板机设了AllowTcpForwarding no/DisableForwarding,后面全断——这是服务端配置,得找管理员。 - host key 反复问——每跳独立验。trust 一次即可;服务器换 key 了按正常 SSH 流程清 known-hosts。
- 关标签页链全断——设计如此:跳跃活在跟会话绑定的
conns里。重连整条重建;真不能断的活儿放目标机 tmux 里,再配会话保活防闲置杀。
速查
- 最终目的地 = 书签 host。跳跃列表 = 中间节点,按拨号顺序,
👤 -> hop1 -> hop2 -> target。 - 每跳:host + 端口 + 用户 + 自己的凭证(agent / 跳板机
~/.sshkey / 存的密码 / 证书 / profile),"从书签选择"可一键填表。 - v1.50.65 起列表顺序 = 连接顺序,老书签有一次性警告 + wiki 链接。
- 引擎:每跳一次
forwardOut、每跳一个 ssh2Client,随标签页同生共死。VNC/RDP 跳跃走动态 SOCKS 代理。 - 跳跃 + 隧道可组队:先跳进内网,再
-L把 DB 端口带出来,一个书签全办。 - CLI 对应:单跳
ssh -J jumper@bastion dbadmin@10.0.0.5,多跳ssh -J bastion,gateway target。
下一篇:Electerm SSH 全解看认证、隧道、NetBird 怎么跟跳跃组队——只要端口不要 shell 就看SSH 隧道。
