我们在做完linux ssh 免密登录后,通常会执行一些自动化任务(比如启动Spark集群),也就是需要ssh到每台节点执行相同命令。但是有一个问题就是如果 known_hosts 文件中不存在这个ip的话,在第一次连接时会弹出确认公钥的提示,需要手动输入 yes,才能继续往下进行。输入yes 后会将公钥添加到 .ssh/known_hosts 中,下次连接时就不需要再次确认了。但是如果节点比较多的话,假如有100个节点,那么我们需要手动输入100次 yes 比较麻烦。本文就是记录如何通过配置或者命令来解决这个问题,方便我们后面执行相关的操作。
ECDSA
cat .ssh/known_hosts
[192.168.1.2]:6233 ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBAymd866NPMmHBlwT3noxxuWqqLcnfMBf5fqgUtP2uaXmNoEApOa7go5RSSx4xzO8CP1u0fOVyOqEYMYJU5S2GQ=
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地址 |
如果没有指定正确的端口,不报错也不返回任何信息(正常应该返回对应的公钥信息),第一次使用如果因为没有使用正确的端口导致不返回任何信息,会使人产生疑惑,误认为该命令不好使~
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之间是并行执行的,没有先后顺序
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为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"
但是有些自动化脚本可能不太好添加配置,对于这种方式就不合适了。
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