ssh代理是一个程序,它可以帮助我们管理私钥,ssh-agent即为ssh代理程序。

那么什么时候需要ssh代理帮助我们管理私钥呢?当遇到如下情况时,我们会需要ssh代理。

1、使用不同的密钥连接到不同的主机时,需要手动指定对应的密钥,ssh代理可以帮助我们选择对应的密钥进行认证,不用手动指定密钥即可进行连接。

2、当私钥设置了密码,我们又需要频繁的使用私钥进行认证时,ssh代理可以帮助我们免去重复的输入密码的操作。

上述两种情况我们会一一道来,不过在描述它们之前,我们先来了解一下怎样使用ssh代理。

启动ssh代理并添加密钥

首先,如果想要使用ssh代理,我们则需要先启动ssh代理,也就是启动ssh-agent程序,如下两条命令都可以启动代理,但是略有不同。

ssh-agent $SHELL

eval `ssh-agent`

如果你最小化安装了centos,那么你执行上述命令时,可能会提示找不到ssh-agent命令,此时你需要安装openssh-clients,安装后即可使用上述命令。

当我们使用”ssh-agent $SHELL”命令时,会在当前shell中启动一个默认shell,作为当前shell的子shell,ssh-agent程序会在子shell中运行,当执行”ssh-agent $SHELL”命令后,我们也会自动进入到新创建的子shell中,centos中,默认shell通常为bash,所以,在centos中上述命令通常可以直接写为ssh-agent bash,当然,如果你的默认shell已经指定为其他shell,比如csh,那么你也可以直接使用ssh-agent csh,效果都是相同的,我们来实验一下。

当前使用的centos系统的默认shell为bash,在未启动ssh-agent程序时,我们在当前bash中执行pstree命令,查看sshd的进程树,如下

然后,执行”ssh-agent $SHELL”命令(注意:SHELL为大写),启动ssh代理,执行此命令后,再次使用pstree命令,查看sshd的进程树

在原来的bash中新生成了一个子bash,ssh-agnet运行在子bash中,我们的命令也同样在子bash中执行。

此时,在当前会话中,我们已经可以使用ssh-agent了,ssh-agent会随着当前ssh会话的消失而消失,这也是一种安全机制,比如,退出当前子shell,再次查看进程树。

[root@server01 ~]# exit
exit

可以看到ssh-agent已经不再存在了,如果你的服务器中开启了图形化环境,使用”ps -ef | grep ssh-agent”命令查找ssh-agent进程,仍然能够看到一个ssh-agent进程,这个ssh-agent进程是跟随图形化界面开机启动的,但是通常,服务器中很少会开启图形化界面,所以我们不用在意它。

虽然我们已经知道了怎样启动ssh-agent,但是,如果想让ssh代理帮助我们管理密钥,还需要将密钥添加到ssh代理中

刚才执行了ssh-agent $SHELL命令,现在试试 eval `ssh-agent` 命令。

eval `ssh-agent`命令并不会启动一个子shell,而是会直接启动一个ssh-agent进程,示例如下

[root@server01 ~]# eval `ssh-agent`
Agent pid 37776
[root@server01 ~]# pstree

可以看到,ssh-agent进程已经启动了,此刻,如果我们推出当前bash,此ssh-agnet进程并不会自动关闭,所以,我们应该在退出当前bash之前,手动的关闭这个进程,在当前bash中,使用ssh-agent -k命令可以关闭对应的ssh-agent进程,但是,如果在退出了当前bash以后再使用’ssh-agent -k’命令,是无法关闭对应的ssh-agent进程的,除非使用kill命令,当然,其实在使用 ssh-agent $SHELL 命令时,也可以使用’ssh-agent -k’命令关闭ssh代理。

好了,我们已经了解了怎样启动ssh代理,以及怎样关闭ssh代理,但是,我们还没有真正的使用过代理,如果想要真正的使用ssh代理帮助我们管理密钥,还需要将密钥添加到代理中,添加密钥需要使用到ssh-add命令

ssh-add命令的使用方法非常简单,示例如下

ssh-add  ~/.ssh/id_rsa_custom

上述命令表示将私钥id_rsa_custom加入到ssh代理中,如果你没有正确的启动ssh-agent,那么你在执行ssh-add命令时,可能会出现如下错误提示。

Could not open a connection to your authentication agent.

完成上述步骤后,ssh代理即可帮助我们管理id_rsa_custom密钥了,那么有哪些具体的使用场景呢,我们继续聊。

ssh代理帮助我们选择对应的私钥进行认证

前一篇文章中,我们总结了基于密钥进行认证的方法,比如,我们在生成密钥对时,可以手动指定密钥的名称,而不是使用默认的密钥名称,示例如下:

[root@server01 ~]# ssh-keygen 
Generating public/private rsa key pair.
Enter file in which to save the key (/root/.ssh/id_rsa): /root/.ssh/id_rsa_test1
Enter passphrase (empty for no passphrase): 
Enter same passphrase again: 
Your identification has been saved in /root/.ssh/id_rsa_test1.
Your public key has been saved in /root/.ssh/id_rsa_test1.pub.
The key fingerprint is:
SHA256:X+3iV0UbGX2tPfXRPnQfINoB3orEkXz42mgDOnNQ/vg root@server01
The key's randomart image is:
+---[RSA 2048]----+
|      ..o..o ...*|
|     ..+o.+ o  *O|
|    o  ooo o  .=@|
|   . o. ...  ..+*|
|    o +.S.  . . +|
|   + o * o . .  .|
|    + o . . . .. |
|       E   . ..  |
|            ..   |
+----[SHA256]-----+
[root@server01 ~]# ssh-copy-id -i /root/.ssh/id_rsa_test1.pub root@192.168.0.221
/usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: "/root/.ssh/id_rsa_test1.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.221's password: 

Number of key(s) added: 1

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

[root@server01 ~]# ssh root@192.168.0.221
root@192.168.0.221's password: 

如上例所示,我们将公钥id_rsa_test1.pub发送给了192.168.0.221的root用户,然后在A机器(192.168.0.220)上连接到C机器(192.168.0.221)时,仍然提示我们输入root@192.168.0.221的密码,这是因为ssh基于密钥进行认证时,默认会使用~/.ssh/id_rsa进行认证,当你使用非默认名称的私钥进行认证时,需要手动指明对应的私钥,如果不指明对应的私钥,ssh仍然会默认使用~/.ssh/id_rsa进行认证,上例就是这种情况,由于我们没有使用~/.ssh/id_rsa进行认证,同时没有指明对应的私钥,ssh会使用id_rsa与id_rsa_test1.pub进行匹配,它们本来就不是一对密钥,自然无法认证成功,所以ssh仍然提示我们输入密码,我们可以使用 -i 选项指定对应的私钥文件进行认证,示例如下

[root@server01 ~]# ssh -i /root/.ssh/id_rsa_test1 root@192.168.0.221
Last login: Wed Dec 30 16:11:27 2020 from server01
[root@server02 ~]# 

如上例所示,指明对应的私钥后,即可正常的使用密钥进行认证,从而免去输入用户的密码。

如果我们手中有很多密钥对,它们对应的公钥被不同的服务器所持有,那么,我们连接不同的服务器时,就需要手动指定对应的不同的私钥,而ssh代理可以帮助我们管理这些私钥,从而避免手动的指定私钥。

示例如下

[root@server01 ~]# ssh-agent bash
[root@server01 ~]# ssh-add /root/.ssh/id_rsa_test1
Identity added: /root/.ssh/id_rsa_test1 (/root/.ssh/id_rsa_test1)
[root@server01 ~]# ssh root@192.168.0.221
Last login: Wed Dec 30 16:20:05 2020 from server01
[root@server02 ~]# 

如上例所示,我们启动了ssh-agent进程,然后将私钥id_rsa_test1加入到了ssh代理中,再次使用非默认名称的私钥进行认证时,并不用指明密钥,ssh-agent会帮助我们选择对应的私钥,进行正确的认证,当本机有多个密钥对,并且它们的公钥分布于很多不同的机器时,会非常有用。

ssh代理能够免去重复输入私钥密码的操作

当我们为私钥设置了密码,ssh基于密钥进行认证时,会提示输入私钥的密码,输入正确的私钥密码,才能够使用对应私钥进行认证,示例如下

生成密钥对,同时指定私钥的密码

[root@server02 ~]# ssh-keygen -f ~/.ssh/id_rsa_test2 -P'123456'  
Generating public/private rsa key pair.
Your identification has been saved in /root/.ssh/id_rsa_test2.
Your public key has been saved in /root/.ssh/id_rsa_test2.pub.
The key fingerprint is:
SHA256:TodsdT4tyAWcS4ah74pbVbIy6ayb61tIjrLq7ck9br0 root@server02
The key's randomart image is:
+---[RSA 2048]----+
|        .+..     |
|       .. =.     |
|      . .oo.o    |
|       + B.= .   |
|    . + S + + .  |
|   + + O .   o   |
|. . o * o        |
| oo oO o         |
|=..*%BoE.        |
+----[SHA256]-----+
[root@server02 ~]# 

[root@server01 .ssh]# ssh-keygen
Generating public/private rsa key pair.
Enter file in which to save the key (/root/.ssh/id_rsa): /root/.ssh/id_rsa_test2
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /root/.ssh/id_rsa_test2.
Your public key has been saved in /root/.ssh/id_rsa_test2.pub.
The key fingerprint is:
SHA256:DSPuClMA0lnPS49eS9FQpZHBveV4AjjWDfQXfGjlyto root@server01
The key’s randomart image is:
+—[RSA 2048]—-+
|o. o. .**B…o.|
|..o o +o=+o =o.|
| . =.+.o..*…|
| . o = = +oo. |
| . + S . oo |
| . o o . o |
| o o . . E |
| o . |
| . |
+—-[SHA256]—–+

[root@server02 ~]# ssh-copy-id -i ~/.ssh/id_rsa_test2.pub root@192.168.0.221
/usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: "/root/.ssh/id_rsa_test2.pub"
The authenticity of host '192.168.0.221 (192.168.0.221)' can't be established.
ECDSA key fingerprint is SHA256:tcswoU/iM4uZXPrY28mUh7YlQvl/DHE1SeLwIX0mhs0.
ECDSA key fingerprint is MD5:ff:8b:91:0c:a0:38:44:5c:67:31:f1:64:91:8c:79:18.
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.221's password: 

Number of key(s) added: 1

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

[root@server02 ~]# 

指定对应私钥连接远程用户,提示输入对应私钥的密码,正确的输入私钥的密码,即可连接到远程用户

[root@server01 .ssh]# ssh -i /root/.ssh/id_rsa_test2 root@192.168.0.221
Last login: Wed Dec 30 16:27:53 2020 from server01
[root@server02 ~]# ssh-agent bash
[root@server02 ~]# ssh-add /root/.ssh/id_rsa_test2
Enter passphrase for /root/.ssh/id_rsa_test2: 
Identity added: /root/.ssh/id_rsa_test2 (/root/.ssh/id_rsa_test2)

ssh代理能够免去重复输入私钥密码的操作

当我们为私钥设置了密码,ssh基于密钥进行认证时,会提示输入私钥的密码,输入正确的私钥密码,才能够使用对应私钥进行认证,示例如下

生成密钥对,同时指定私钥的密码

ssh-keygen -f ~/.ssh/id_rsa_test2 -P’123456′

  

将公钥添加到远程用户的公钥认证文件中,提示输入远程用户的密码。

ssh-copy-id -i ~/.ssh/id_rsa_test2.pub root@192.168.0.221

root@192.168.0.221’s password:

  

指定对应私钥连接远程用户,提示输入对应私钥的密码,正确的输入私钥的密码,即可连接到远程用户

ssh -i ~/.ssh/id_rsa_test2 root@192.168.0.221

Enter passphrase for key ‘/root/.ssh/id_rsa_test2’:

  

但是,如果为私钥设置了密码,每次使用私钥进行认证连接是,都会要求输入私钥密码,如果你在当前ssh会话中需要反复的连接到远程用户,那么反复的输入复杂的私钥密码,的确会比较麻烦,ssh-agent可以帮助我们,在一个ssh会话中,只要输入一次私钥密码,在同一ssh会话中之后再次使用到相同的私钥时,即可不用再次输入对应密码,示例如下。

[root@server01 .ssh]# ssh-agent bash
[root@server01 .ssh]# ssh-add /root/.ssh/id_rsa_test2
Enter passphrase for /root/.ssh/id_rsa_test2: 
Identity added: /root/.ssh/id_rsa_test2 (/root/.ssh/id_rsa_test2)
[root@server01 .ssh]# ssh -i /root/.ssh/id_rsa_test2 root@192.168.0.221
Last login: Wed Dec 30 16:42:57 2020 from server02
[root@server02 ~]# 

如上图所示

第1步:启动ssh代理

第2步:将对应私钥添加到ssh代理中,在添加私钥时,会提示输入私钥的密码,此时,正确的输入私钥密码即可将私钥添加到ssh代理中。

第3步:连接到远程用户,并使用对应私钥进行认证,已经不用输入私钥密码,即可连接到远程用户,从远程用户的会话中退出,回到当前ssh会话中。

第4步:在当前会话中,再次连接到远程用户,同样没有提示输入密码。

从上述示例可以看出,在同一个ssh会话中,ssh-agent可以帮助我们免去重复输入私钥密码的操作。

管理ssh代理中的密钥

如果我们想要查看ssh代理中已经添加了哪些私钥,该怎样查看呢?使用’ssh-add -l’即可查看,示例如下

[root@server01 .ssh]# ssh-add -L
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCRifoMpVSR1txm8ek63wLeF6B6tm42mKRVTPcStinxyLeYpmi/IcJDOemopA6fHNeyupNoLluwCpeSukv8IBAqt1oeE+QI+rmecPBl/d9n1XoeI8tIrm1cMp8pz7CEX5k7ijquSnvMU8YsLM5J7a4S2GX+mXHAw/NUU6MhkhDjEmDVV7+qpvOVpK6rWALl05crMavyDujDi30Fyy7tsn8RNap2ja/1TWewegBD/bpW/9RwGcWKrekpz+UqGB/D33/gx7TTKeXaeIaOgEqqsuJB0ztZrsTjtQDvO28L+KvZOpIaxTMuyKKgBtU1SEIu6m/gKH0z3UUCsbMVoaTi4mUV /root/.ssh/id_rsa_test2
[root@server01 .ssh]# ssh-add -l
2048 SHA256:DSPuClMA0lnPS49eS9FQpZHBveV4AjjWDfQXfGjlyto /root/.ssh/id_rsa_test2 (RSA)

如果我们想要从代理中移除某个已经添加的私钥,可以使用’ssh-add -d’命令指定要移除的私钥,示例如下

[root@server02 .ssh]# ssh-add -d /root/.ssh/id_rsa_test2

我们也可以一次性清空代理中的所有私钥,使用’ssh-add -D’命令即可。

如果我们想要临时锁定ssh代理,则可以对ssh代理添加密码,并进行锁定,锁定后的ssh代理无法继续帮助我们管理私钥,除非解锁以后,才能正常的帮助我们管理私钥,示例如下,在正常情况下,ssh代理可以帮助我们管理私钥,我们可以使用’ssh-add -x’命令对代理加锁,加锁时会提示输入密码,这个密码在解锁时需要用到,加锁后,再次连接远程用户时,ssh代理已经失效,除非我们对代理进行解锁,使用’ssh-add -X’命令(大写X)对代理解锁,解锁时需要输入加锁时设定的密码,解锁后,ssh代理恢复正常。

总结

启动ssh-agent

如下两种方式均可启动ssh-gent

方式一:创建子shell,在子shell中运行ssh-agent进程,退出子shell自动结束代理。

 
 
Shell

 

1

sshagent $SHELL

方式二:单独启动一个代理进程,退出当前shell时最好使用ssh-agent -k关闭对应代理

 
 
Shell

 

1

eval `sshagent`

  

关闭ssh-agent

 
 
Shell

 

1

sshagent k

  

将私钥添加到ssh代理

 
 
Shell

 

1

sshadd ~/.ssh/key_name

  

查看代理中的私钥

 
 
Shell

 

1

sshadd l

  

查看代理中的私钥对应的公钥

 
 
Shell

 

1

sshadd L

  

移除指定的私钥

 
 
Shell

 

1

sshadd /path/of/key/key_name

  

移除代理中的所有私钥

 
 
Shell

 

1

sshadd D

  

锁定ssh代理

锁定时需要指定锁定密码,锁定后的ssh代理暂时不能帮助我们管理私钥

 
 
Shell

 

1

sshadd x

  

解锁ssh代理

解锁时需要输入创建锁时设定的密码,解锁后ssh代理可正常工作

 
 
Shell

 

1

sshadd X