4. 密钥同步失败常见原因概览

密钥同步这件事,说简单也简单,说复杂也确实坑多。我自己带团队做运维那几年,光密钥同步失败就把我折腾了不知道多少个深夜。大多数问题其实都集中在几个固定的“雷区”里。摸清这些雷区,排查起来就能少走弯路。

下面我把常见原因分成五类,每类都附上我自己的踩坑经历。你把它当个清单用,排查时对号入座就行。

核心观点:95% 的密钥同步失败都可以归因于网络、权限、格式、主机互信或服务状态这五个方面。不要一上来就抓包看日志,先检查这五项。

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 或 非本用户拥有
避坑指南: 我曾经用 root 账号把同步脚本跑了一遍,密钥文件属主变成了 root,普通用户根本读不了。同步成功后永远登录不上。记住:密钥文件的属主必须与登录用户一致。

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(但注意安全风险)
我的建议: 生产环境别关 StrictHostKeyChecking,而是用 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。
密钥同步失败常见原因逻辑结构图 密钥同步失败原因概览(五大类) 密钥同步失败 网络不可达/防火墙 文件权限/属主错误 密钥格式不匹配 主机互信/known_hosts 服务配置/策略限制 排查顺序建议 1. 网络连通性(ping/telnet/ssh -v) 2. 密钥文件权限与属主(ls -la ~/.ssh/) 3. 密钥格式与内容(ssh-keygen -l -f) 4. known_hosts 冲突 + SSHD 配置生效检查

这张图把五类原因放在了同一个结构里。你排查时,从上到下过一遍,基本上能解决绝大部分问题。如果还不行,那就要进到具体环节的深层排查了,比如看 /var/log/secure 或者 /var/log/auth.log。

最后补一句: 我个人习惯在每台新机器初始化时就把这五项检查写成一个脚本,每次跑完自动输出结果。这样密钥同步失败时,我不用手工一条条敲命令,直接看脚本报告就能定位。后面几章会讲到更细的排查工具链。