【发布时间】:2010-12-28 09:05:50
【问题描述】:
我使用了一个由大约 30 台机器组成的集群,这些机器最近都使用新的 OpenSSH 主机密钥重新配置。当我尝试登录其中一个时,我收到此错误消息(为简洁起见,删除了许多行):
@ WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! @
The fingerprint for the RSA key sent by the remote host is
52:bb:71:83:7e:d0:e2:66:92:0e:10:78:cf:a6:41:49.
Add correct host key in /home/nr/.ssh/known_hosts to get rid of this message.
Offending key in /home/nr/.ssh/known_hosts:50
我可以手动删除违规行,在这种情况下,我会收到关于 IP 地址的不同投诉,这需要手动删除 another 行,我不想重复此练习 29 次.我想写一个程序来做到这一点。不幸的是,.ssh 文件中的行不再像在早期版本中那样以明文形式包含主机名和 IP 地址。
这是我的问题:
- 给定主机名和 IP 地址,我如何编写程序来找出我的
~/.ssh/known_hosts的哪些行存储了该主机或 IP 地址的 SSH 主机密钥?
如果我能恢复这些信息,我想我可以自己做剩下的事情。
脚注:我更喜欢用 bash/ksh/sh 或 C 或 Lua 编写代码;我的 Perl 和 Python 都生疏了。
说明:
我不想删除整个文件并重新填充它;它包含一百多个经过验证的密钥,我不想重新验证。
无论我是维护一个主副本还是多个副本,清除大量过时主机密钥的问题仍然存在。
回答
这是我使用 ssh-keygen -F 编写的 Lua 脚本:
#!/usr/bin/env lua
require 'osutil'
require 'ioutil'
local known = os.getenv 'HOME' .. '/.ssh/known_hosts'
local function lines(name)
local lines = { }
for l in io.lines(name) do
table.insert(lines, l)
end
return lines
end
local function remove_line(host)
local f = io.popen('ssh-keygen -F ' .. os.quote(host))
for l in f:lines() do
local line = l:match '^# Host %S+ found: line (%d+) type %u+$'
if line then
local thelines = lines(known)
table.remove(thelines, assert(tonumber(line)))
table.insert(thelines, '')
io.set_contents(known, table.concat(thelines, '\n'))
return
end
end
io.stderr:write('Host ', host, ' not found in ', known, '\n')
end
for _, host in ipairs(arg) do
local ip = os.capture('ipaddress ' .. host)
remove_line(host)
remove_line(ip)
end
【问题讨论】:
-
你不能删除整个文件吗?
-
创建一个“主版本”并将其推送到所有机器?我将 $HOME 保存在 NFS 上,所以它在任何地方都是同一个文件......
-
这并不能解决您的问题,但如果您或其他任何人希望将来禁用这种烦人的行为,请在您的 ssh_config 中将 HashKnownHosts 设置为“no”。