ssh和ssh-copy-id以及批量多机无密码登陆详解

  本文主要围绕着ssh服务以及如何通过ssh-copy-id实现无密码登陆。

  1. sshd 服务以及配置   2.ssh-copy-id命令的使用以及原理。3.批量多机互相信任。

1. sshd 服务

  SSH(Secure Shell)是一种能够以安全的方式提供远程登录的协议,也是目前远程管理Linux系统的首选方式。在此之前,一般使用FTP或Telnet来进行远程登录。但是因为它们以明文的形式在网络中传输账户密码和数据信息,因此很不安全,很容易受到黑客发起的中间人攻击,这轻则篡改传输的数据信息,重则直接抓取服务器的账户密码。

  想要使用SSH协议来远程管理Linux系统,则需要部署配置sshd服务程序。sshd是基于SSH协议开发的一款远程管理服务程序,不仅使用起来方便快捷,而且能够提供两种安全验证的方法:

     基于口令的验证—用账户和密码来验证登录;

     基于密钥的验证—需要在本地生成密钥对,然后把密钥对中的公钥上传至服务器,并与服务器中的公钥进行比较;该方式相较来说更安全。

  sshd服务的配置信息保存在/etc/ssh/sshd_config文件中,以下是对于一些常用的配置进行记录。

 port 22 默认的sshd服务端口
ListenAddress 0.0.0.0 设定sshd服务器监听的IP地址
HostKey /etc/ssh/ssh_host_rsa_key RSA私钥存放的位置
HostKey /etc/ssh/ssh_host_ecdsa_key ECDSA私钥存放的位置
HostKey /etc/ssh/ssh_host_ed25519_key ed25519私钥存放的位置
PermitRootLogin yes 设定是否允许root管理员直接登录
StrictModes yes 当远程用户的私钥改变时直接拒绝连接
MaxAuthTries 6 最大密码尝试次数
MaxSessions 10 最大终端数
PasswordAuthentication yes 是否允许密码验证
PermitEmptyPasswords no 是否允许空密码登录(很不安全)

  ssh命令

     常用选项

      -p     指定远程主机端口

      -i      指定认证文件

      -o    ConnectionAttempts=NUM  连接失败后重试次数

      -o    ConnectTimeout=SEC        连接超时时间

      -o    StrictHostKeyChecking=no            自动去拉取主机key文件

      -o   PasswordAuthentication=no          禁止密码认证

  示例:  

ssh  root@ip  -p端口号

2. ssh-copy-id命令的使用以及原理、

  2.1 生成“密钥对”。

    ssh-keygen 

      常用参数 [-t dsa | ecdsa | ed25519 | rsa | rsa1],指定加密方式。

    示例: 

[root@localhost .ssh]# ssh-keygen  -t ecdsa
Generating public/private ecdsa key pair.
Enter file in which to save the key (/root/.ssh/id_ecdsa): 按回车键或设置密钥的存储路径
Enter passphrase (empty for no passphrase): 直接按回车键或设置密钥的密码
Enter same passphrase again: 再次按回车键或设置密钥的密码
Your identification has been saved in /root/.ssh/id_ecdsa.
Your public key has been saved in /root/.ssh/id_ecdsa.pub.
The key fingerprint is:
SHA256:yMZjxaP0yC2OQrRPEexfsbMweSPVVEvK88cvqUGA root@localhost.localdomain
The key's randomart image is:
+---[ECDSA 256]---+
|   ..   ..oo.o   |
|    .. .o+oo+    |
|  ... .oEo=o     |
| . ..*=O*o +     |
|  o ..%*S+o .    |
| . o =.o.. . .   |
|  . o . .   o    |
|   .     . .     |
|         .o      |
+----[SHA256]-----+
[root@localhost .ssh]# ll
total 8
-rw------- 1 root root 227 Jun 10 23:55 id_ecdsa #私钥
-rw-r--r-- 1 root root 188 Jun 10 23:55 id_ecdsa.pub   #公钥

  2.2 ssh-copy-id将公钥上传到远程主机

    基于密钥验证,当我们讲公钥上传到我们需要远程登陆的主机的authorized_keys文件后我们就可以直接远程到主机了。

    ssh-copy-id 常用选项:

      -i  指定公钥文件

    示例:

[root@localhost yum.repos.d]# ssh-copy-id  -i /root/.ssh/id_ecdsa.pub  root@192.168.123.218
/usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: "/root/.ssh/id_ecdsa.pub"
The authenticity of host '192.168.123.218 (192.168.123.218)' can't be established.
ECDSA key fingerprint is SHA256:Qh+4R5mpwlU6kK3bf0k53ngm+WpKKnfvL1ZJo+YM3ic.
ECDSA key fingerprint is MD5:d2:76:6d:33:45:e1:23:83:13:aa:10:ce:f7:1f:9f:32.
Are you sure you want to continue connecting (yes/no)? yes   #输入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.123.218's password:   #填入密码

Number of key(s) added: 1

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

    将公钥添加到远程主机后我们可以直接通过密钥登陆了。

我们这里要着重讲下ssh-copy-id的这个命令做了什么事。

  1.第一它将本地的主机的公钥添加到远程主机的authorized_keys文件里。

  2.第二它将在本地的用户的家目录的 .ssh/目录下新建了一个known_hosts文件。

下面我们来做个实验,假如我们需要将本地主机到远程主机的信任解除掉,那么我们需要将远程主机的authorized_keys里的本地主机的密钥清除掉。

  清除authorized_keys里的指定内容后,我们再用ssh ip直接登陆远程主机,会发现我们再次登陆需要输入密码,但是我们不需要像第一次远程登陆那样先要输入yes再输入密码。这个是由于本地的known_hosts文件导致的,本地known_hosts文件已经将远程主机

的连接信息储蓄在这里了,当我们清除了里面的远程主机的连接信息的时候,我们再进行登陆的时候就要yes后再输入密码。    

  如果我们想以后不管远程登陆任何主机都可以直接输入密码不需要那个验证,那么我们可以修改配置文件达到这个效果。

打开/etc/ssh/ssh_config文件:
找到:
# StrictHostKeyChecking ask
修改为
StrictHostKeyChecking no

3.批量多机互相信任。

  我在网上看到一种方法是将所有的主机设置成一样的公钥和私钥,也就是在一台电脑上面生成密钥文件后,然后分发到所有的主机中。这种方法有好处也有坏处,我们这里用另外一种方法。

思路:第一步在每个主机上生成密钥后,并把所有主机的公钥都传输到一台主机的authorized_keys文件里,然后将authorized_keys文件再分发到所有主机,这样就可以实现互相信任了,但是还是会有一个问题就如何将所有的主机的公钥文件添加到一台主机的authorized_keys文件里(复制下来然后添加进)。

  主要文件 believe.sh  ,sshcopy.exp ,sshkeygen.exp,hosts文件。

  github 位置:https://github.com/tobewithyou1996/ssh-batch-believe.git(直接在博客这里复制容易有编码问题,所以在这里放上github位置)

  believe.sh文件

#!/bin/bash
#检查本地是否有密钥文件,没有则添加。
./sshkeygen.exp
#循环取出ip和密码
for i in $(cat ./hosts )
do
    #取出ip和密码
    IP=$(echo "${i}" |awk -F":" '{print $1}')
    PW=$(echo "${i}" |awk -F":" '{print $2}')
    #将本地的公钥复制到远程主机
    ./sshcopy.exp $IP  $PW
    #将脚本sshkeygen.exp复制到远程主机
    scp -p ./sshkeygen.exp   $IP:/root/
    #远程主机安装expect
    ssh root@$IP "yum install expect -y "
    #远程主机创建密钥文件
    ssh root@$IP "/root/sshkeygen.exp&"
    #将远程主机的公钥添加到本地authorized_keys文件
    ssh root@$IP "cat ~/.ssh/*.pub" >>./authorized_keys
done
#将本地的公钥复制到远程主机
for i in $(cat ./hosts)
do
     IP=$(echo "${i}" |awk -F":" '{print $1}')
   #将本地主机的公钥文件添加到authorized_keys文件
     cat ~/.ssh/*.pub >>./authorized_keys
scp ./authorized_keys $IP:~/.ssh/authorized_keys done

  sshcopy.exp(脚本的功能是:将本地的公钥文件上传到远程主机)该文件本地权限要是可执行权限.

#!/usr/bin/expect -d  
set ip [lindex $argv 0]
set pw [lindex $argv 1]
set timeout 60
spawn ssh-copy-id $ip
expect {
#"*yes/no" {send "yes
"; exp_continue}
#如果上面这行注释了,我们需要在/etc/ssh/ssh_config 将# StrictHostKeyChecking ask 修改为 StrictHostKeyChecking no。 "password:" {send "$pw "} } expect eof

  sshkeygen.exp(脚本功能是:判断是否有密钥文件,有则退出,没有则创建)该文件本地权限要是755.

#!/usr/bin/expect -d
set timeout 90
spawn ssh-keygen
expect {
".ssh/id_rsa" {send "
";exp_continue}
"Overwrite (y/n)?" exit
"Enter passphrase" {send "
";exp_continue}
"Enter same passphrase again:" {send "
"}
}
expect eof

  hosts文件(包含ip和密码,ip和密码之间以":"间隔)

149.28.244.75:*p8V1xG{7)%sQV!
149.28.245.101:K(1q@jsvM@UVZtk

以上就可以批量实现主机直接互信(可以直接远程登陆)

将所有主机的密钥文件设置一致的脚本链接是:http://www.cnblogs.com/kevingrace/p/9063745.html

原文地址:https://www.cnblogs.com/operationhome/p/9166583.html