如果指纹已知,如何以编程方式接受 SSH 主机密钥?

如果指纹已知,如何以编程方式接受 SSH 主机密钥?

我不想使用-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) 等等。

相关内容