SSH连接主机的IP为何被加入.ssh/known_hosts?及Bitbucket密钥更新问题
known_hosts哈希IP问题 问题背景
近期Bitbucket更新了SSH主机密钥,我需要给多台Ubuntu系统更新.ssh/known_hosts文件以适配变更。
最初我尝试用命令删除旧条目:
ssh-keygen -R bitbucket.org
但该命令仅删除了bitbucket.org域名的哈希条目,文件中仍残留着Bitbucket解析出的IP地址(比如2406:da00:ff00::22cd:e0db)的哈希条目——我可以确定所有连接都是通过域名发起的,从未直接使用IP地址,但这些IP哈希条目并未被清理。
单独针对每个IP执行ssh-keygen -R [IP地址]可以删除对应条目,但Bitbucket有大量IPv4和IPv6地址,无法预知每台系统中缓存了哪些IP的哈希记录。无奈之下我清空了known_hosts:
echo > .ssh/known_hosts
然后通过官方渠道获取最新密钥写入文件:
curl https://bitbucket.org/site/ssh > .ssh/known_hosts
操作后连接恢复正常,但再次连接时,SSH又自动生成了对应Bitbucket IPv6地址的哈希条目,且该条目的密钥与已添加的bitbucket.org密钥完全一致。这让我担心下次遇到GitHub、GitLab等服务商的密钥轮换时,又要重复清空文件的操作。
核心疑问
- 明明通过域名连接,为什么对应的IP地址会被哈希存入
known_hosts? - 能否阻止这种IP哈希条目的生成?
- 能否通过关联的主机名批量删除这些IP哈希条目?
解决方案
1. IP哈希条目生成的原因
SSH客户端默认开启了HashKnownHosts配置(多数系统默认启用)。当开启该配置时,SSH不仅会哈希存储你输入的主机名,还会将域名解析后的实际连接IP也哈希后存入known_hosts。这么做的目的是:
- 下次连接时如果域名解析到同一IP,可直接匹配验证,减少解析和验证开销
- 避免明文存储IP地址,提升隐私性
2. 阻止IP哈希条目生成的方法
针对特定主机修改SSH配置(推荐),编辑~/.ssh/config(个人配置)或/etc/ssh/ssh_config(全局配置),添加以下内容:
Host bitbucket.org HashKnownHosts no VerifyHostKeyDNS yes
HashKnownHosts no:关闭哈希存储,known_hosts中将明文存储bitbucket.org的条目,不会生成IP相关的哈希记录VerifyHostKeyDNS yes:开启DNS主机密钥验证,SSH会自动通过DNS查询Bitbucket的官方密钥记录并验证,无需手动维护IP条目
如果想要全局禁用哈希存储,可在配置中直接设置HashKnownHosts no,但会降低隐私性,不建议全局配置。
3. 批量删除关联主机名的IP哈希条目
如果不想清空整个known_hosts,可通过以下步骤批量清理关联的IP哈希条目:
首先,导出所有与bitbucket.org相关的哈希条目明文对应关系:
ssh-keygen -H -F bitbucket.org
然后用脚本批量提取关联IP并删除:
# 自动提取并删除所有关联bitbucket.org的IP哈希条目 ssh-keygen -H -F bitbucket.org | grep -E "^# Host bitbucket.org found:" -A1 | grep -v "^#" | awk '{print $1}' | while read ip; do ssh-keygen -R "$ip" done
该脚本会自动识别所有与bitbucket.org关联的IP地址,逐个执行删除命令清理对应哈希条目。
内容的提问来源于stack exchange,提问作者Dr. Gianluigi Zane Zanettini

