重装VPS、更换IP对应的服务器,或重新生成SSH主机密钥后,客户端可能拒绝连接,并显示 REMOTE HOST IDENTIFICATION HAS CHANGED。这不是普通的密码错误,而是本机保存的旧主机指纹与服务器当前返回的指纹不一致。
正确处理顺序是先确认服务器身份,再删除旧记录并接受新密钥。 如果跳过指纹核对,真正的中间人攻击也可能被误当成一次正常重装。

先理解这条警告保护了什么
SSH首次连接服务器时,会把服务端主机公钥写入当前用户的 known_hosts。以后每次连接,客户端都会比较已保存公钥与服务端返回值。主机密钥变化时,严格校验会中止连接,避免用户在不知情的情况下把账号口令或会话交给错误的主机。
常见的合理变化包括重装系统、从快照恢复后重建SSH配置、云平台更换实例,以及同一IP重新分配给另一台机器。但IP劫持、DNS污染、代理配置错误也能制造相同现象。看到警告只能说明身份发生冲突,不能直接证明变化是安全的。
保存错误信息中的关键线索
先重新执行一次带详细日志的连接,不要输入密码:
ssh -vvv root@203.0.113.10
记录警告中显示的算法、SHA256指纹、发生冲突的文件和行号。例如记录可能来自 ~/.ssh/known_hosts,也可能来自系统级 /etc/ssh/ssh_known_hosts。使用非默认端口时,主机通常以 [地址]:端口 的形式保存。
不要看到提示给出的删除命令就立刻执行。 先把旧指纹与当前连接目标、变更时间和服务器工单对应起来,这些信息有助于判断是否连错IP或入口。
从可信通道读取新指纹
最可靠的方法是在云服务商控制台、串口控制台或机房带外管理中登录服务器,直接计算主机公钥指纹:
sudo ssh-keygen -lf /etc/ssh/ssh_host_ed25519_key.pub
sudo ssh-keygen -lf /etc/ssh/ssh_host_ecdsa_key.pub
sudo ssh-keygen -lf /etc/ssh/ssh_host_rsa_key.pub
把输出与客户端警告逐字符比较,并确认算法一致。若服务器由其他管理员维护,应通过已验证的沟通渠道索取指纹,不能在同一条可疑网络路径上临时获取后直接信任。
只有可信控制台中的新指纹与SSH警告完全一致,才进入更新步骤。 无法核对时,应暂停登录并检查DNS、跳板机、代理和IP归属。
定位known_hosts中的旧记录
可先查询而不修改文件:
ssh-keygen -F 203.0.113.10
ssh-keygen -F '[203.0.113.10]:2222'
如果使用域名,还要分别查询域名和解析后的IP。启用了哈希主机名时,手工搜索文件可能看不到明文地址,ssh-keygen -F 仍能正确匹配。
检查当前SSH配置最终使用的主机名、端口和用户:
ssh -G production-vps | grep -Ei '^(hostname|port|user|userknownhostsfile) '
这能发现别名实际指向旧IP,或者配置了自定义 UserKnownHostsFile。先定位真实记录,避免误删其他服务器的可信密钥。
使用ssh-keygen安全移除旧条目
确认本次变更合法后,先备份用户级文件:
cp ~/.ssh/known_hosts ~/.ssh/known_hosts.backup-$(date +%F-%H%M%S)
ssh-keygen -R 203.0.113.10
非默认端口必须带方括号:
ssh-keygen -R '[203.0.113.10]:2222'
OpenSSH手册说明,-R 会从指定known_hosts文件中移除该主机的全部密钥,也能处理哈希记录。如果冲突出现在自定义文件,可增加 -f 指定路径。不要用清空整个known_hosts文件解决单台主机冲突,否则会丢失所有已建立的信任记录。
重新连接并接受正确的新密钥
再次发起连接:
ssh root@203.0.113.10
客户端会把它视为首次见到的主机,并显示新指纹。再次与可信控制台记录比对,确认无误后输入 yes。连接成功后可以复查保存结果:
ssh-keygen -F 203.0.113.10
接受提示不是验证动作本身,真正的验证是独立比较指纹。 如果重新连接得到的指纹与前一步不同,应立即停止并调查网络路径。
自动化环境不要关闭严格校验
CI、备份脚本和批量运维常因无人确认而失败。不要为了恢复任务,长期设置 StrictHostKeyChecking no 或把 UserKnownHostsFile 指向 /dev/null。这会让自动化失去主机身份保护。
更稳妥的做法是在镜像发布或主机重建流程中,通过可信资产系统分发新公钥,更新专用known_hosts文件,再启动任务。临时使用 accept-new 只会自动接受从未见过的主机,已经变化的密钥仍会被拒绝,不能替代指纹管理。
排除域名、代理和集群入口问题
同一域名如果轮询到多台拥有不同主机密钥的服务器,客户端会间歇报错。先检查解析结果:
getent ahosts ssh.example.com
ssh -G ssh.example.com | grep -Ei '^(hostname|proxyjump|proxycommand|port) '
跳板机和 ProxyJump 场景要区分目标主机与跳板机的警告。集群应统一采用主机证书、稳定入口,或让每个节点使用独立名称。不要让一个主机名随机代表多套未经统一签发的密钥。
需要先在隔离环境演练重装和密钥轮换时,可使用 萤光云 创建同版本测试机,也可通过 LightNode 准备短期节点。测试时只复制无敏感信息的SSH配置,不要带入生产私钥。
建立可追溯的主机密钥轮换流程
计划重装前,先导出现有指纹并通知使用者;完成部署后,从控制台采集新指纹,经资产系统或签名公告分发。大型环境可使用SSH主机证书,让客户端信任内部CA,而不是逐台维护裸公钥。
轮换记录至少包含主机名、IP、算法、旧新指纹、变更人和时间。可追溯的变更能把安全警告变成可验证事件,而不是依赖运维人员凭感觉点击确认。
完成后的验收检查
从实际使用的客户端再次连接,确认不再出现主机密钥冲突;用 ssh-keygen -F 检查新记录只指向预期主机;核对自动化任务的专用known_hosts也已同步。
还要保留一次失败场景测试:向临时文件写入错误密钥,确认严格校验确实会阻止连接。验收标准是新指纹可信、正常连接成功、错误指纹仍会被拒绝,并且旧记录备份可回溯。
常见问题
服务器刚重装,可以直接执行ssh-keygen -R吗?
仍应先通过云控制台核对新指纹。知道发生过重装只能解释变化原因,不能证明当前网络返回的就是那台服务器。
删除known_hosts会不会影响登录密钥?
删除的是服务端身份记录,不是客户端私钥或服务端 authorized_keys。但清空整个文件会破坏对其他主机的信任记录。
同一个IP经常复用,怎样减少人工处理?
为实例使用稳定域名、自动分发可信指纹,或部署主机证书体系。不要以关闭严格校验换取方便。
温馨提示
处理主机密钥变化时,账号密码正确与否并不重要,核心是确认连接对象。在新指纹未通过独立通道验证之前,不要输入密码、验证码或执行任何远程命令。


