SSH主机密钥验证失败(Host key verification failed)深度解析与解决方案

SSH主机密钥验证失败(Host key verification failed)深度解析与解决方案

在使用SSH(Secure Shell)或基于SSH协议的工具(如SCP、SFTP)进行远程连接或文件传输时,"Host key verification failed"是极为常见的报错。该报错看似阻碍了操作,实则是SSH协议的核心安全机制在发挥作用------防止中间人攻击(Man-in-the-Middle, MITM)。本文将结合实际报错案例,从原理、原因、解决方案到安全实践,全面拆解这一问题,帮助读者彻底掌握应对方法。

一、问题概述:从实际报错场景切入

本人在执行SCP命令向Kali虚拟机传输文件时,触发如下报错,导致文件传输失败:

bash 复制代码
scp Cwebscanner-master.zip kali@192.168.1.69:/home/kali/Downloads
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@    WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!     @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!
Someone could be eavesdropping on you right now (man-in-the-middle attack)!
It is also possible that a host key has just been changed.
The fingerprint for the ED25519 key sent by the remote host is
SHA256:m8h8XK+PhKKNRqus76T/PBSW+icLoCyPmAF9OVYO3Xg.
Please contact your system administrator.
Add correct host key in /Users/liuxiaowei/.ssh/known_hosts to get rid of this message.
Offending ED25519 key in /Users/liuxiaowei/.ssh/known_hosts:29
Host key for 192.168.1.69 has changed and you have requested strict checking.
Host key verification failed.
scp: Connection closed

核心报错信息:Host key verification failed (主机密钥验证失败),且明确指出了问题位置------本地/Users/liuxiaowei/.ssh/known_hosts文件的第29行,存储着与目标主机(192.168.1.69)不匹配的旧密钥。

二、核心原理:SSH主机密钥验证机制

要理解报错原因,首先要掌握SSH的主机密钥验证逻辑,这是SSH安全通信的基础:

  1. 首次连接:密钥存储 :当用户首次通过SSH/SCP连接远程主机时,远程主机会向客户端发送自己的主机密钥 (类似主机的"数字身份证",由远程主机的SSH服务生成,默认存储在/etc/ssh/目录下,如ssh_host_ed25519_key.pubssh_host_rsa_key.pub等)。客户端会提示用户确认该密钥的真实性,用户输入"yes"后,客户端会将该主机的IP/域名与对应的密钥指纹,存储到本地用户目录下的~/.ssh/known_hosts文件中。

  2. 后续连接:密钥校验 :之后每次连接该远程主机时,客户端会先从known_hosts文件中读取该主机的历史密钥,再与远程主机当前发送的密钥进行比对。若一致,则正常建立连接;若不一致,则立即触发"Host key verification failed"报错,拒绝连接------这是为了防止攻击者伪造目标主机,拦截并窃取用户的账号密码、传输数据等敏感信息。

关键结论:该报错的本质是"本地记录的远程主机密钥"与"远程主机当前的实际密钥"不匹配,SSH为规避中间人攻击风险,强制终止连接。

三、报错原因:正常场景与风险场景区分

密钥不匹配并非都是攻击导致,需先区分正常场景与风险场景,避免盲目操作带来安全隐患。

1. 正常场景(无安全风险,最常见)

这类场景是由于远程主机的密钥发生了合法变更,导致本地记录失效:

  • 远程主机重装系统/SSH服务:重装系统或重新安装、重置SSH服务时,原有的主机密钥会被删除,SSH服务会自动生成新的密钥对,导致密钥变更。

  • 手动重置远程主机SSH密钥 :管理员手动删除/etc/ssh/目录下的主机密钥文件,重启SSH服务后,系统会生成新密钥。

  • 目标IP被重新分配:若远程主机使用DHCP自动获取IP,路由器重启或IP租期到期后,该IP可能被分配给其他新设备,新设备的SSH密钥与原主机不同,导致校验失败。

2. 风险场景(需紧急排查)

若排除上述正常场景,则需警惕中间人攻击:攻击者在客户端与目标主机之间伪造一个"代理",冒充目标主机与客户端通信,试图窃取用户的登录凭证(如用户名、密码)或传输的敏感数据。此时,客户端接收到的是攻击者的密钥,而非真实目标主机的密钥,因此触发校验失败。

四、解决方案:分步操作,先验证再解决

解决问题的核心逻辑是:先验证远程主机的真实性,排除攻击风险;再清除本地旧密钥,重新建立合法的密钥关联。以下是详细步骤:

步骤1:验证远程主机真实性(关键!不可跳过)

这是保障安全的核心步骤,需通过"可信渠道"确认目标主机(192.168.1.69)的当前SSH密钥是否合法:

  1. 获取可信渠道访问:直接操作目标主机(如Kali虚拟机本机登录),或通过其他已确认安全的网络连接(如直接连接目标主机所在的局域网,而非公共网络)访问。

  2. 查看远程主机当前SSH密钥指纹 :登录目标主机后,执行如下命令,查看其当前的ED25519密钥指纹(报错中明确提示是ED25519密钥,优先验证该类型):

    `# 查看ED25519密钥指纹(推荐,安全性更高)

    ssh-keygen -lf /etc/ssh/ssh_host_ed25519_key.pub

若需验证其他类型密钥(如RSA),可执行

ssh-keygen -lf /etc/ssh/ssh_host_rsa_key.pub`

  1. 比对指纹一致性 :命令执行后,会输出类似如下结果:
    256 SHA256:m8h8XK+PhKKNRqus76T/PBSW+icLoCyPmAF9OVYO3Xg root@kali (ED25519)
    若输出的指纹(SHA256:后面的字符串)与报错中显示的指纹完全一致,则说明是正常的密钥变更,可继续后续操作;若不一致,立即停止当前操作,排查网络是否存在中间人攻击(如检查路由器设备、断开公共网络连接等)。

步骤2:清除本地旧的无效密钥

报错信息中已明确指出无效密钥的位置:Offending ED25519 key in /Users/liuxiaowei/.ssh/known_hosts:29,即known_hosts文件的第29行是与目标主机不匹配的旧密钥。可通过两种方式清除:

方式1:精准删除(推荐,不影响其他主机记录)

直接删除known_hosts文件中指定行的旧密钥,适合熟悉命令行的用户:

  • macOS系统 :sed命令需添加-i ''参数(表示原地编辑,不生成备份文件):
    sed -i '' '29d' /Users/liuxiaowei/.ssh/known_hosts

  • Linux系统 :sed命令直接使用-i参数:
    sed -i '29d' /home/用户名/.ssh/known_hosts

  • 通用方式(自动匹配IP删除) :若不确定行号,可使用ssh-keygen -R命令,自动删除指定IP的所有密钥记录(推荐新手使用):
    ssh-keygen -R 192.168.1.69

    执行后会提示"Host 192.168.1.69 found: line 29",并自动删除该行记录。

方式2:手动编辑文件(适合新手)

通过文本编辑器打开known_hosts文件,手动删除无效行:

  1. 打开文件:

    • macOS:执行open /Users/liuxiaowei/.ssh/known_hosts,用文本编辑打开;

    • Linux:执行vim /home/用户名/.ssh/known_hosts,或使用图形化文本编辑器(如gedit);

    • Windows(WSL或Git Bash):执行notepad ~/.ssh/known_hosts

  2. 找到包含"192.168.1.69"的行(报错提示第29行),删除该行内容;

  3. 保存文件并关闭。

步骤3:重新执行SSH/SCP命令,建立新的密钥关联

清除旧密钥后,重新执行最初的SCP命令(或SSH登录命令):

bash 复制代码
scp Cwebscanner-master.zip kali@192.168.1.69:/home/kali/Downloads

此时客户端会提示确认新的主机密钥,类似如下信息:

bash 复制代码
The authenticity of host '192.168.1.69 (192.168.1.69)' can't be established.
ED25519 key fingerprint is SHA256:m8h8XK+PhKKNRqus76T/PBSW+icLoCyPmAF9OVYO3Xg.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes

输入"yes"后,客户端会将新的密钥指纹写入known_hosts文件,后续连接即可正常建立,文件传输顺利完成。

五、常见问题排查:解决操作中的小插曲

在执行上述步骤时,可能会遇到以下问题,可针对性解决:

1. 执行sed命令报错"invalid command code ."(macOS)

原因:macOS的sed命令与Linux不同,缺少-i ''参数会导致报错。解决方案:严格按照步骤2中macOS的命令格式执行,即添加-i ''

2. 清除旧密钥后,重新连接仍报错

排查方向:

  • 是否清除了正确的IP/行号?可重新执行ssh-keygen -R 192.168.1.69确认;

  • 远程主机是否再次变更了密钥?重新验证远程主机的密钥指纹;

  • 是否存在多个known_hosts文件?检查当前登录用户是否正确(如root用户与普通用户的known_hosts文件路径不同)。

3. 无法直接操作远程主机,无法验证密钥指纹

解决方案:通过其他可信方式联系远程主机管理员,获取当前的密钥指纹;或暂时断开公共网络,连接到目标主机所在的私有局域网后再验证,避免在不可信网络中盲目操作。

六、安全最佳实践:规避后续同类问题

为减少"Host key verification failed"报错的发生,同时提升SSH通信的安全性,建议遵循以下最佳实践:

1. 给远程主机配置静态IP

若远程主机(如虚拟机、服务器)使用DHCP自动获取IP,建议手动配置静态IP,避免IP被重新分配给其他设备,导致密钥不匹配。

2. 记录可信主机的密钥指纹

首次连接远程主机时,将其密钥指纹记录在安全的地方(如本地加密文档),后续出现报错时,可快速比对验证,无需重复操作远程主机。

3. 禁用弱密钥算法,使用强密钥

远程主机端可配置SSH服务,禁用RSA(小于2048位)等弱密钥算法,仅启用ED25519、ECDSA等强密钥算法,提升安全性:

bash 复制代码
# 编辑SSH配置文件
vim /etc/ssh/sshd_config

# 添加如下配置,禁用弱算法
HostKeyAlgorithms ssh-ed25519-cert-v01@openssh.com,ecdsa-sha2-nistp256-cert-v01@openssh.com
KexAlgorithms curve25519-sha256@libssh.org,ecdh-sha2-nistp256

# 重启SSH服务生效
systemctl restart sshd

4. 避免临时关闭严格密钥检查(不推荐)

部分用户为图方便,会在SSH/SCP命令中添加-o StrictHostKeyChecking=no参数,临时跳过密钥验证:

bash 复制代码
scp -o StrictHostKeyChecking=no Cwebscanner-master.zip kali@192.168.1.69:/home/kali/Downloads

该方式仅适用于本地测试环境(如虚拟机频繁重装),绝对禁止在生产环境或公共网络中使用,会直接暴露在中间人攻击风险中。

5. 定期更新SSH密钥

为提升安全性,建议定期(如每6个月)在远程主机端重置SSH密钥,并同步更新本地known_hosts文件中的记录。

七、总结

"Host key verification failed"报错并非故障,而是SSH协议的安全防护机制在生效。解决问题的关键是"先验证,再清除"------先通过可信渠道确认远程主机的真实性,排除中间人攻击风险,再清除本地的旧密钥记录,重新建立合法的密钥关联。

在实际操作中,切勿为了快速解决问题而跳过安全验证步骤;同时,通过配置静态IP、记录密钥指纹、使用强密钥算法等最佳实践,可有效减少同类报错的发生,保障远程通信的安全性。

相关推荐
core5122 小时前
Nginx 实战:如何通过代理转发下载中文文件并保留原文件名
运维·nginx·代理·下载·转发
OliverH-yishuihan2 小时前
在 Windows 上安装 Linux
linux·运维·windows
zclinux_2 小时前
【Linux】虚拟化的内存气泡
linux·运维·服务器
松涛和鸣3 小时前
DAY33 Linux Thread Synchronization and Mutual Exclusion
linux·运维·服务器·前端·数据结构·哈希算法
CCI3443 小时前
Remote ssh无法连接?
运维·ssh
星瞰物联3 小时前
融合北斗与天通卫星通信技术的堤坝水文监测卫星图传系统
网络·物联网·安全·系统架构
技术小李...3 小时前
docker下mysql更改密码后WordPress提示无法连接数据库问题
运维·docker·容器
周杰伦_Jay3 小时前
【GRPC 和 HTTP】设计目标和底层实现
网络·网络协议·http
Focussend智能化营销3 小时前
2026破局:以营销自动化成熟度Macom模型为鞍,驰骋增长新赛道!
运维·自动化