Linux 批量添加 known_hosts

发布时间:2024年01月17日

前言

我们在做完linux ssh 免密登录后,通常会执行一些自动化任务(比如启动Spark集群),也就是需要ssh到每台节点执行相同命令。但是有一个问题就是如果 known_hosts 文件中不存在这个ip的话,在第一次连接时会弹出确认公钥的提示,需要手动输入 yes,才能继续往下进行。输入yes 后会将公钥添加到 .ssh/known_hosts 中,下次连接时就不需要再次确认了。但是如果节点比较多的话,假如有100个节点,那么我们需要手动输入100次 yes 比较麻烦。本文就是记录如何通过配置或者命令来解决这个问题,方便我们后面执行相关的操作。

  • ssh 到其他节点

  • 启动Spark集群

  • 输入yes后连接成功,并添加公钥到 known_hosts,这里的密钥类型为 ECDSA

cat .ssh/known_hosts
[192.168.1.2]:6233 ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBAymd866NPMmHBlwT3noxxuWqqLcnfMBf5fqgUtP2uaXmNoEApOa7go5RSSx4xzO8CP1u0fOVyOqEYMYJU5S2GQ=

解决方案一:ssh-keyscan

ssh-keyscan 命令是一个收集大量主机公钥(HostKey)的实用工具。设计目的是帮助建立和验证 known_hosts 文件。使用了非阻塞 socket I/O 函数, 尽可能多的并行访问多个主机, 因此它的效率很高. 它可以在数十秒内采集某域中 1,000 台主机的密钥, 即使某些主机离线或不使用 ssh. 扫描的时候无须登录目标主机, 也不涉及任何加密操作.

引用自:https://developer.aliyun.com/article/1114651

命令

ssh-keyscan -p 6233 -t ECDSA -f hostlist.txt >> .ssh/known_hosts

通过这个命令可以将 hostlist.txt 中所有的ip对应的HostKey添加到known_hosts中,这样我们再执行自动化脚本ssh这些节点时就不弹出公钥确认的提示了。

hostlist.txt 是我们要添加的所有的ip

cat hostlist.txt

192.168.1.1
192.168.1.2
192.168.1.3
192.168.1.4
192.168.1.5
192.168.1.6
192.168.1.7
192.168.1.8
192.168.1.9
192.168.1.10

结果:

用法

ssh-keyscan
usage: ssh-keyscan [-46cHv] [-f file] [-p port] [-T timeout] [-t type]
                   [host | addrlist namelist] ...

参数解释

参数释义
-p远程主机的端口
-f从指定文件中读取主机列表
-t密钥类型:rsa、dsa、ecdsa、ed25519,不缺分大小写
-T设置尝试连接超时时间
-v显示调试信息
-4强制只使用 IPv4 地址
-6强制只使用 IPv6 地址
host、addrlist namelist主机名或IP地址,可以以空格分割写多个ip地址
  • -p port

如果没有指定正确的端口,不报错也不返回任何信息(正常应该返回对应的公钥信息),第一次使用如果因为没有使用正确的端口导致不返回任何信息,会使人产生疑惑,误认为该命令不好使~

  • host | addrlist namelist 示例
ssh-keyscan -p 6233 -t ECDSA 192.168.1.1
ssh-keyscan -p 6233 -t ECDSA 192.168.1.1 192.168.1.2

多个ip之间是并行执行的,没有先后顺序

  • -t type
    有四种密钥类型 rsa、dsa、ecdsa、ed25519,上面的命令中指定的类型为 ECDSA,之所以使用类型 ECDSA 是因为我们在最上面的图片中可以的看到,在输入yes 后会自动添加公钥到 known_hosts,类型就是 ECDSA。当然使用其他类型也可以满足我们的需求,只要有一种类型的的公钥加到known_hosts文件中,再次连接时就不会弹出公钥提示了。不同的服务器支持的类型不太一致,有资料说和ssh协议版本有关系,但是并不确定是否正确。我的服务器支持三种类型,不支持 dsa 类型,不清楚为啥。

如果不指定密钥类型,则返回所有的支持的公钥类型对应的公钥。known_hosts 存在其中一个或多个公钥类型对应的公钥,连接时都不会弹出公钥提示。

ssh-keyscan -p 6233 -t rsa 192.168.1.1
ssh-keyscan -p 6233 -t dsa 192.168.1.1
ssh-keyscan -p 6233 -t ecdsa 192.168.1.1
ssh-keyscan -p 6233 -t ed25519 192.168.1.1
ssh-keyscan -p 6233 192.168.1.1

有资料说支持哪些类型可以在 /etc/ssh/sshd_config 查看,确实有四个密钥类型,并且注释掉了一个dsa,好像对应上了,但是当我修改配置,将其他三个都注释掉或部分注释掉并重启sshd服务后,ssh-keyscan 返回的结果是一样的,还是同样支持三种密钥类型,不支持dsa~

HostKey /etc/ssh/ssh_host_rsa_key
#HostKey /etc/ssh/ssh_host_dsa_key
HostKey /etc/ssh/ssh_host_ecdsa_key
HostKey /etc/ssh/ssh_host_ed25519_key

注释

在上面截图中,我们可以看到没个密钥类型返回的信息中都包含一条注释:

# 192.168.1.1:6233 SSH-2.0-OpenSSH_7.4

这个好像是ssh的版本信息,不知道是在哪里输出的,怎么去掉打印这个注释,注释信息不会添加到 known_hosts 中。

解决方案二:StrictHostKeyChecking

  • StrictHostKeyChecking=no 安全级别最低。如果对应的HostKey在本地不存在,会自动添加到known_hosts,并且给出一个警告。
  • StrictHostKeyChecking=ask 默认的级别。如果对应的HostKey在本地不存在,弹出公钥提示。
  • StrictHostKeyChecking=yes 安全级别最高,如果对应的HostKey在本地不存在,认证失败,拒绝连接。

所以我们可以修改StrictHostKeyChecking为no,这样再第一次连接时就会自动将HostKey添加到known_hosts文件中了,之后再将StrictHostKeyChecking改为默认的ask级别。

全局配置

/etc/ssh/ssh_config 客户端配置,不需要重启sshd服务,注意不是/etc/ssh/sshd_config (服务端配置),这俩文件名相似,我最开始没注意到是客户端配置,修改错了,并且重启sshd服务,导致sshd服务启动失败,会导致服务器无法ssh远程连接。

用户环境配置

~/.ssh/config,如果没有这个文件,可以新建,然后添加 StrictHostKeyChecking=no,这个配置文件要比全局配置文件优先级高。

命令参数

ssh -p 6233 -o StrictHostKeyChecking=no 192.168.1.2

这个需要修改对应的自动化脚本,比如修改 spark的配置文件 spark-env.sh,添加配置

export SPARK_SSH_OPTS="-p 6233 -o StrictHostKeyChecking=no"

但是有些自动化脚本可能不太好添加配置,对于这种方式就不合适了。

参考

修改 known_hosts 位置

UserKnownHostsFile ~/dkl/known_hosts

同样是客户端配置,可以在 ~/.ssh/config/etc/ssh/ssh_config 添加该配置项

ssh -p 6233 -o StrictHostKeyChecking=no -o UserKnownHostsFile=~/dkl/known_hosts 192.168.1.2

文章来源:https://blog.csdn.net/dkl12/article/details/135640474
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。