4. 密钥同步失败常见原因概览
密钥同步这件事,说简单也简单,说复杂也确实坑多。我自己带团队做运维那几年,光密钥同步失败就把我折腾了不知道多少个深夜。大多数问题其实都集中在几个固定的“雷区”里。摸清这些雷区,排查起来就能少走弯路。
下面我把常见原因分成五类,每类都附上我自己的踩坑经历。你把它当个清单用,排查时对号入座就行。
4.1 网络不可达与防火墙拦截
这是个老生常谈的问题,但偏偏最容易忽略。我记得有一次,从北京机房往上海机房同步密钥,反复报错“Connection refused”。我排查了半小时,最后发现上海那台机器的 22 端口被安全组给封了。
常见网络层面的原因有:
- 目标主机 IP/域名解析错误: /etc/hosts 配错了,或者 DNS 缓存过期。
- 防火墙/安全组拦截: 默认 SSH 端口 22,有时运维策略改了端口,两边配置没对齐。
- 公司网络策略限制: 有些内网环境不允许跨网段直接 SSH,必须走跳板机。
- 临时性网络抖动: 丢包率高但没完全断,导致 SSH 握手超时。
ssh -v user@hostname 看看 debug 输出。如果是“Connection timed out”,就优先查防火墙;如果是“Connection refused”,基本是服务没起来。
4.2 文件系统权限与属主错误
嗯,这里要注意——密钥文件的权限要求非常严格。OpenSSH 的设计思路是:一旦文件权限太宽,它就认为文件不安全,直接拒绝使用。我曾在生产环境犯过一个错误:把 id_rsa 的权限设成了 644,结果同步回来的私钥根本用不了。
正确的权限要求:
| 文件/目录 | 建议权限 | 错误示例(会导致失败) |
|---|---|---|
| ~/.ssh 目录 | 700 (drwx------) | 755 (drwxr-xr-x) |
| ~/.ssh/id_rsa (私钥) | 600 (-rw-------) | 644 (-rw-r--r--) |
| ~/.ssh/id_rsa.pub (公钥) | 644 (-rw-r--r--) | 600 或 777 一般没事,但建议统一 |
| ~/.ssh/authorized_keys | 600 (-rw-------) | 644 会导致 SSH 忽略该文件 |
| ~ 家目录 | 755 或 700 | 777 或 非本用户拥有 |
4.3 密钥格式与内容不匹配
密钥格式这事,我见过太多次了。有人在 Windows 上用 Puttygen 生成了 .ppk 格式,然后直接拷到 Linux 上。ssh-keygen -i 转换一下就好的事,非要手动改格式,结果首行没加 -----BEGIN OPENSSH PRIVATE KEY-----,直接报错。
常见格式问题:
- 公钥内容多余空格或换行: 粘贴时不小心多了回车,SSH 解析到第二行就停了。
- 密钥类型不兼容: 源端用 ed25519,目标端 SSHD 配置里禁用了 ed25519 算法。
- 私钥加密方式不匹配: 同步时用的 scp 正常,但 SSH 登录时报“Load key failed format”。
- Windows 行尾符污染: 在 Windows 下编辑过密钥文件,换行变成
\r\n,Linux 下 OpenSSH 直接罢工。
ssh-keygen -l -f id_rsa 看看文件能不能被正常解析。如果报错“invalid format”,那百分百是格式问题。
4.4 主机互信与 known_hosts 冲突
密钥同步之后,客户端 ~/.ssh/known_hosts 里可能记录着旧的主机公钥。如果目标机器重装过系统,或者 IP 被重新分配了,客户端就会报“WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED”。
我遇到过最奇葩的一次:两台机器 A 和 B 互为备份,我把 B 的密钥自动同步到 A,结果 A 上的 known_hosts 还记录着 B 旧系统的指纹,每次 SSH 都弹警告,导致自动化脚本卡死。
解决方案无非两种:
- 手动删除旧指纹:
ssh-keygen -R hostname - 配置 StrictHostKeyChecking: 在自动化脚本里加
ssh -o StrictHostKeyChecking=no(但注意安全风险)
ssh-keyscan 批量预置 known_hosts,这样既安全又能避免手动干预。
4.5 服务配置与认证策略限制
最后一个大块是 SSHD 配置。很多人只关注密钥本身,忘了看服务器端的设置。下面几个参数最容易出问题:
| 参数 | 作用 | 常见坑 |
|---|---|---|
| PubkeyAuthentication | 是否允许公钥认证 | 被设为 no,只允许密码认证 |
| AuthorizedKeysFile | 公钥存放路径 | 默认是 .ssh/authorized_keys,但被改成了别的路径 |
| PasswordAuthentication | 是否允许密码认证 | 被设为 no,但密钥认证又没成功,两边都进不去 |
| PermitRootLogin | 是否允许 root 登录 | 设为 prohibit-password,但密钥同步到 root 时被拒绝 |
| UsePAM | 是否启用 PAM 模块 | PAM 限制了某些用户的登录时间或 IP |
我建议你养成习惯:同步密钥之后,先 sshd -T | grep -E 'pubkey|authorized|password|permitroot' 看一下当前生效配置。如果配置文件和实际生效的不一样(因为 Include 指令),你查几天都查不出来。
/etc/ssh/sshd_config 后忘了重启服务,结果手动 ssh -o PubkeyAuthentication=yes 测试时一直失败。最后发现服务端根本没加载新配置。记住:改完 ssd_config 一定要 systemctl restart sshd 或者 reload。
这张图把五类原因放在了同一个结构里。你排查时,从上到下过一遍,基本上能解决绝大部分问题。如果还不行,那就要进到具体环节的深层排查了,比如看 /var/log/secure 或者 /var/log/auth.log。