关于ssh免密登陆脚本实现的一些想法

通常ssh免密应用在集群机器的管理方面,免密的目的是为了运维的方便,但不是说就没有安全可言。虽然,免密的时候执行ssh-keygen 的时候,没有并且也不应该输入密码,但通过密钥分发的操作后,只有具有密钥公钥的机器才可以免密登陆,也就是说这一把钥匙还是在你自己的手中,因此,安全性还是无需担心的。

那么,我们可以仔细的观察一下公钥的生成过程,来看一看到底有什么奥秘在其中。

这是第一次生成密钥公钥。

[root@centos8 ~]# ssh-keygen 
Generating public/private rsa key pair.
Enter file in which to save the key (/root/.ssh/id_rsa): 
Enter passphrase (empty for no passphrase): 
Enter same passphrase again: 
Your identification has been saved in /root/.ssh/id_rsa.
Your public key has been saved in /root/.ssh/id_rsa.pub.
The key fingerprint is:
SHA256:2ZeFwHUnjvudfz3KsWtlDUnw/sTaD5uzc7dcnXTn/Qc root@centos8
The key's randomart image is:
+---[RSA 2048]----+
|         ...o.o .|
|          .. *.o |
|            o.+. |
|         o   =o. |
|        S . + .o*|
|           . .EXO|
|             .*+X|
|            ..*=@|
|            .=*BX|
+----[SHA256]-----+

删除以上生成的公钥,在重新生成一次公钥,我们可以发现公钥的值并不是一样的,虽然也是无密码验证生成公钥。由此,我们可以得出一个结论:密钥的公钥是独一无二的一个指纹类存在,因此,它的安全性是可以保证的。

[root@centos8 ~]# rm -rf /root/.ssh/id_rsa
[root@centos8 ~]# ssh-keygen 
Generating public/private rsa key pair.
Enter file in which to save the key (/root/.ssh/id_rsa): 
Enter passphrase (empty for no passphrase): 
Enter same passphrase again: 
Your identification has been saved in /root/.ssh/id_rsa.
Your public key has been saved in /root/.ssh/id_rsa.pub.
The key fingerprint is:
SHA256:bkqGD/Tmv/QtAjxMT+83oeTNec8TXborUrV2udSSff0 root@centos8
The key's randomart image is:
+---[RSA 2048]----+
|                 |
|                 |
|                 |
|      . .     . .|
|    .+ oS.   . =*|
|   . o=.. o o *+B|
|    o =o++ = +.+=|
|     B +..*.B o+E|
|      +.oo.+.+.o+|
+----[SHA256]-----+

以上是关于ssh免密登陆前的准备工作的一些说明。




手动分发本机的公钥到目标机器上实现本机到目标机的免密登陆过程。

那么,ssh的公钥分发在某些时候对于运维来说是一个不小的挑战,挑战性在于如果有几十或者上百台上千台机器需要做免密的时候,ssh-copy-id 命令是很大的一个工作量,比如,

我现在有两台机器,192.168.0.16免密登陆到192.168.0.18 这个机器,那么,我们手动操作的步骤大概如下:

[root@centos6 ~]# ssh-copy-id 192.168.0.18
/usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: "/root/.ssh/id_rsa.pub"
/usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed
/usr/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed -- if you are prompted now it is to install the new keys
root@192.168.0.18's password: 

Number of key(s) added: 1

Now try logging into the machine, with:   "ssh '192.168.0.18'"
and check to make sure that only the key(s) you wanted were added.

首先,需要目标的ip,这还是在省略用户名的情况下,如果是ssh到普通用户,可能ssh-copy-id 命令后还需要加用户名,其次,需要输入目标机器的密码进行一次验证,这样我们才能实现192.168.0.16机器到192.168.0.18机器的免密登陆,如果是十几台机器,并且密码都一致的情况下,可能还可以接受,如果上百台或者上千台机器了,毫无疑问,实现免密登陆工作将会是一场灾难。




那么,我们如何应对以上手动实现ssh免密登陆所带来的挑战呢??毫无疑问,shell脚本是一个十分不错的选择。

使用脚本实现免密登陆的三个前提:

1.本机生成指纹公钥,也就是执行 ssh-keygen 命令,并且该命令执行中不输入任何密码。

2,既然是脚本执行ssh-copy-id 命令,那么,从手动免密登陆过程中可以看到,本机和目标机有两个互动的地方,首先是确认将要连接(第一次ssh连接会让你输入yes才可继续),其次是输入目标机的密码,脚本做这些互动,那么最简单的方式是使用expect命令来完成自动化的互动。因此,需要在本机安装expect命令。安装命令为: yum install expect -y

3目标机器的信息收集,我们需要告诉脚本,目标机器的ip,将要免密登陆的用户,和这个免密登陆用户在目标机器上的密码。这些信息必须是准确无误的。通常,我们写一个文本文档,如下面所示:

[root@centos6 ~]# vim host.txt 
192.168.0.16 root 密码
192.168.0.17 root 密码
192.168.0.18 root 密码

以实际使用的密码为准哦,我这出于保护自己隐私,用汉字密码代替我实际在使用的密码了,请注意哦

 

如果,以上三个准备工作都做好了,那么, 我们就可以编写shell脚本并执行这个脚本,从而实现快速的一个本机到N个目标机器的免密登陆,脚本内容如下:

#!/bin/bash
# FileName:             freelogin.sh
# Revision:             1.0
# Date:                 2021-03-20
# Author:               zsk_john
# Description:          the script for auto-ssh-login without password
set -e
expectIsExists=`rpm -qa | grep expect`
 if [ -z $expectIsExists ]
 then
      yum -y install expect
 fi
while read host;do
        ip=`echo $host | cut -d " " -f1`
        username=`echo $host | cut -d " " -f2`
        password=`echo $host | cut -d " " -f3`
expect <<EOF
        spawn ssh-copy-id -i $username@$ip
        expect {
                "yes/no" {send "yes\n";exp_continue}
                "password" {send "$password\n"}
        }
        expect eof
EOF
done < /root/host.txt

脚本名称建议为freelogin.sh ,目标机器信息清单文件为root目录下的host.txt,内容为第三条所列。set -e表示脚本出错即停止,首先,一个if语句检测expect是否安装,如没有则yum安装,通过while循环读取目标机器的ip,用户名,密码,读取一行做一次免密登陆,依次完成直至读取完毕。

执行该脚本,在本案例中,即可实现192.168.0.16 到16,17,18 三台目标机器的免密登陆了。

脚本执行后的输入应该如下所示:

[root@centos6 ~]# bash test.sh 
spawn ssh-copy-id -i root@192.168.0.16
/usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: "/root/.ssh/id_rsa.pub"
The authenticity of host '192.168.0.16 (192.168.0.16)' can't be established.
ECDSA key fingerprint is SHA256:7YlOXTWDqT1fXWhNgJdIxsLI+ggZvk6b8K7Y8iLPpRo.
ECDSA key fingerprint is MD5:1f:78:f8:2c:a7:1e:8d:3f:70:a0:10:72:95:60:9e:ce.
Are you sure you want to continue connecting (yes/no)? yes
/usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed
/usr/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed -- if you are prompted now it is to install the new keys
root@192.168.0.16's password: 

Number of key(s) added: 1

Now try logging into the machine, with:   "ssh 'root@192.168.0.16'"
and check to make sure that only the key(s) you wanted were added.

spawn ssh-copy-id -i root@192.168.0.17
/usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: "/root/.ssh/id_rsa.pub"
The authenticity of host '192.168.0.17 (192.168.0.17)' can't be established.
ECDSA key fingerprint is SHA256:7YlOXTWDqT1fXWhNgJdIxsLI+ggZvk6b8K7Y8iLPpRo.
ECDSA key fingerprint is MD5:1f:78:f8:2c:a7:1e:8d:3f:70:a0:10:72:95:60:9e:ce.
Are you sure you want to continue connecting (yes/no)? yes
/usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed
/usr/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed -- if you are prompted now it is to install the new keys
root@192.168.0.17's password: 

Number of key(s) added: 1

Now try logging into the machine, with:   "ssh 'root@192.168.0.17'"
and check to make sure that only the key(s) you wanted were added.

spawn ssh-copy-id -i root@192.168.0.18
/usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: "/root/.ssh/id_rsa.pub"
The authenticity of host '192.168.0.18 (192.168.0.18)' can't be established.
ECDSA key fingerprint is SHA256:Ji2SvNiOi/WUj96UqB99WTAz9pE01+G3wLRjau76+go.
ECDSA key fingerprint is MD5:43:d7:d7:a7:cb:d9:3c:03:a6:a8:93:d2:29:12:47:4c.
Are you sure you want to continue connecting (yes/no)? yes
/usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed
/usr/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed -- if you are prompted now it is to install the new keys
root@192.168.0.18's password: 

Number of key(s) added: 1

Now try logging into the machine, with:   "ssh 'root@192.168.0.18'"
and check to make sure that only the key(s) you wanted were added.