SSH 密钥网格:per-device 密钥交换与 dropbear 兼容

2026年8月1日| Ruichen Zhou| 约 7 分钟阅读

基础设施要做到“出问题时能远程进去诊断”,设备之间必须能互相 SSH。但怎么布密钥,有个偷懒方案:生成一对密钥,塞进所有机器的 authorized_keys,所有机器共用同一把私钥。

这篇记录为什么没用共享 mesh key,而是做了 per-device 的密钥网格,以及过程中 dropbear 和旧设备带来的几个兼容问题。

1. 为什么不用共享 mesh key

共享密钥部署一次就能让所有机器互通,代价是任何一台的私钥泄露后,整个网格的密钥都得更换。

我的环境里,参与互访的设备性质差异很大:两台 VPS(有公网暴露面)、家里的 N1 和路由器(内网但物理上不在身边)、开发机。VPS 被打穿的概率远高于家里的 N1。如果它们共享一把私钥,VPS 一旦失守,攻击者拿到的私钥能直接登录我家里所有设备。

per-device 的代价是分发次数多:每台设备的公钥要放进其余 N-1 台的 authorized_keys。一台设备泄露后,攻击者只能使用它自己的私钥访问它原本能到达的目标。撤销它的访问权时,从这些目标中删除对应公钥即可,不影响其他设备。

2. per-device 密钥交换

实际拓扑是几台“发起方”(VPS-DE、VPS-HK、N1、开发机)需要 SSH 到一批“目标”(Cudy、AX6、n1-sd,以及彼此)。每台发起方生成自己的 ed25519 密钥,把公钥分发到目标的 authorized_keys。

现代 Linux 设备(VPS、N1)用 OpenSSH,公钥放标准的 ~/.ssh/authorized_keys

# n1 的 authorized_keys(实测 4 条 ed25519,来自各发起方)
ssh-ed25519 AAAA...  vps-de
ssh-ed25519 AAAA...  vps-hk
ssh-ed25519 AAAA...  mac-mini
ssh-ed25519 AAAA...  precision-7920

每条公钥的注释标注来源设备,方便日后审计谁有访问权。ed25519 是首选:密钥短、签名快、安全性足够。除非目标设备不认,否则不用 ECDSA/RSA。

3. dropbear 的 authorized_keys 路径陷阱

OpenWrt 设备(Cudy、AX6)跑的是 dropbear,不是 OpenSSH。第一个问题是 authorized_keys 的路径。

OpenSSH 默认读 ~/.ssh/authorized_keys。OpenWrt 打包的 dropbear 使用 /etc/dropbear/authorized_keys;这不是所有 dropbear 系统的通用路径,dropbear 上游默认读的也是家目录下的 .ssh/authorized_keys,这个路径是 OpenWrt 打包时改的。如果在 OpenWrt 上把公钥放进用户家目录,dropbear 不会读取,SSH 仍会要求密码或拒绝登录。

# Cudy(OpenWrt + dropbear)实测
cat /etc/dropbear/authorized_keys   # 正确路径
# 5 条 ssh-ed25519,来自各发起方

Cudy 的 dropbear 支持 ed25519。不查这个路径差异时,症状就是“公钥已经加入,登录仍被拒绝”。

4. n1-sd:ed25519 公钥未生效,改用 ECDSA

家里还有一台在山东的斐讯 N1,主机名为 n1-sd,与前面运行 OpenSSH 的 N1 是同型号的两台机器,别混淆。n1-sd 使用 dropbear v2018.76,实测放入 /etc/dropbear/authorized_keys 的 ed25519 公钥没有生效,登录仍会失败;换成 ECDSA 公钥后可以正常登录。

需要说明,不能据此断言 v2018.76 不支持 ed25519 用户密钥。具体原因没有确认,可能与该固件编译 dropbear 时的选项有关,也可能是这台机器上 authorized_keys 的路径或权限问题。这里只记录实测现象和实际采用的方案。

实际做法是给 n1-sd 单独生成 ECDSA 密钥。需要访问它的设备都要额外维护一对 ECDSA 密钥,只用于这台设备:

# 发起方为 n1-sd 生成 ECDSA
ssh-keygen -t ecdsa -f ~/.ssh/id_ecdsa -N ""

再在发起方的 SSH 配置中指定这把密钥:

Host n1-sd
  IdentityFile ~/.ssh/id_ecdsa

这就是 per-device 网格里“特例”的部分:大部分设备统一 ed25519,唯独 n1-sd 因为 ed25519 公钥未生效而实际使用 ECDSA。这种特例必须记录下来,不然下次维护的人会困惑“为什么这台要两套密钥”。

5. known_hosts:刷机后的 host key 变化

设备刷机或重装系统后,host key 会变。SSH 客户端之前记下的指纹就对不上了,连接时报:

Host key verification failed.

这次排查 n1-sd 互访时就撞上了。从 N1 跳板 SSH 到 n1-sd,直接报 Host key verification failed。不是密钥授权的问题(authorized_keys 里公钥在),而是 n1-sd 刷机后 host key 变了,N1 的 known_hosts 里还存着旧指纹。

清理方法是删掉 known_hosts 里对应那条:

ssh-keygen -R n1-sd        # 删除旧 host key
ssh n1-sd                  # 重新接受新指纹

这类问题在经常刷机的设备上会反复出现。设备刷机后,各客户端需要删除对应的旧 known_hosts 记录,再核对并接受新指纹。

6. 最终拓扑

密钥网格建好后,互访关系大致是:

  • VPS-DE / VPS-HK / N1:彼此互通(OpenSSH + ed25519)
  • Cudy / AX6:作为目标,dropbear + ed25519,公钥在 /etc/dropbear/authorized_keys
  • n1-sd:作为目标,dropbear v2018.76,ed25519 未生效,实际使用 ECDSA 密钥
  • 开发机:作为发起方,公钥分发到所有需要访问的目标

AX6 因为内存吃紧没装 Tailscale,访问它要经 N1 做 ProxyJump 跳板(ssh -J n1 ax6)。这样 AX6 本身不暴露在 Tailnet,只能通过 N1 中转。

评论