![如果指纹已知,如何以编程方式接受 SSH 主机密钥?](https://linux22.com/image/9440/%E5%A6%82%E6%9E%9C%E6%8C%87%E7%BA%B9%E5%B7%B2%E7%9F%A5%EF%BC%8C%E5%A6%82%E4%BD%95%E4%BB%A5%E7%BC%96%E7%A8%8B%E6%96%B9%E5%BC%8F%E6%8E%A5%E5%8F%97%20SSH%20%E4%B8%BB%E6%9C%BA%E5%AF%86%E9%92%A5%EF%BC%9F.png)
我不想使用-o StrictHostKeyChecking=no
选项,但我想将服务器的公钥保存在文件中,并在每次连接时使用该公钥,即使 IP 地址或端口发生更改。
当-o UserKnownHostsFile=myfile
使用选项时,如果我们通过不同的 IP 连接同一台机器,ssh 仍然会要求验证。
如何判断ssh
将公钥保存在不同的位置并在当前连接中使用该公钥?用法示例:
# there is no 'foo-public.key' file at this moment
ssh -o TheMagicalOption=foo-public.key [email protected] -p 1234
The authenticity of host 'xxxxxxxx' can't be established.
ECDSA key fingerprint is SHA256:LR5wDKrEmHD0QhRcAmxTxBnzWIRmNUfJyeawhKw+W38.
Are you sure you want to continue connecting (yes/no)? [YES]
# 'foo-public.key' is created at this point
on-target $ exit
# another port forward is made, so the same server is on port 5678
ssh -o TheMagicalOption=foo-public.key [email protected] -p 5678
# not asking the same verification question
on-target $
答案1
您可以使用
ssh -o StrictHostKeyChecking=ask \
-o HashKnownHosts=no \
-o CheckHostIP=no \
-o UserKnownHostsFile=example_fp \
-p 1234 [email protected]
获取密钥。
HashKnownHosts=no
确保主机名将以明文形式保存CheckHostIP=no
仅用于通过名称来识别主机
结果example_fp
将是一行,开头如下
[example.com]:1234 ecdsa-sha2-nistp521 AAAA...
当在第一个连接上使用标准端口 22 时,您会看到
example.com ecdsa-sha2-nistp521 AAAA...
因此,要么在第一次连接时使用端口 22,要么随后编辑文件以删除端口号。下次连接时,该行将匹配任何端口号。
答案2
没有这样神奇的选择可以做到这一点。您可以提前手动存储公钥(如果已知),或者使用一些期望脚本,如果指纹“正确”,该脚本将为您写“是”。
答案3
一种解决方法可能是使用ssh-keyscan
作为附加步骤来获取 ssh 指纹,然后用通配符替换主机字段,*
然后再将其保存到文件中。例如:
$ ssh-keyscan -p 1234 example.com | $ ssh-keyscan -p 1234 example.com perl -pe 's/.*? /* /' > example_fp
然后,每当您需要连接到该服务器时,您都可以引用example_fp
(无论端口/dns/ip):
$ ssh -o UserKnownHostsFile=example_fp -p 4321[电子邮件受保护]
答案4
如果您有服务器的 pubkey 文件(副本),正如您的名字所示,您可以使用它来创建一个临时的known_hosts文件,例如:
sshfoo() {
# assumes first arg is always user@host, otherwise adjust
echo ${1#*@} $(cat foo-pubkey) >temp_myhosts
ssh -oUserKnownHostsFile=temp_myhosts "$@"
# or if you don't have anything you need in .ssh/known_hosts,
# just overwrite that and omit the -o
rm temp_myhosts # or just leave it and replace it next time
}
# can use ssh for the function name if you always want this change,
# or if in the cases you don't want it you remember to override
# with command ssh or $(which ssh) or /bin/ssh or whatever
如果您实际上有一个现有的known_hosts行(这是一个主机字段,后跟公钥文件的内容),您可以类似地修改它:
awk -vh="${1#*@}" "{$1=h;print}" <hosts_line >temp_myhosts
或者如果您有一个包含该行的文件,也许是通常的known_hosts:
awk -vh="${1#*@}" "$1~/oldname/{$1=h} 1" <.ssh/known_hosts >temp_myhosts
尤尔·伯连纳 (Yul Brynner) 等等。