SSH-Agent 代理

前言

在我学习 ansible 的时候,其官方文档中提到使用 ssh-agent 来管理密钥,用于免密登录远程节点;经过我的努力研究,终于参透其理,下述通过 5W1H 方法对它的使用进行简单的总结:

What—什么是 ssh-agent ?

SSH-Agent 是一个代理程序,用于帮助我们管理私钥,可以存储用户的身份密钥(identity keys)和密钥密码(passphrases)

Where—哪里会用到 ssh-agent ?

  1. 使用不同的密钥连接到不同的主机时,需要手动指定对应的密钥,ssh代理可以帮助我们选择对应的密钥进行认证,不用手动指定密钥即可进行连接;
  2. 当私钥设置了密码,我们又需要频繁的使用私钥进行认证时,ssh代理可以帮助我们免去重复的输入密码的操作。

When—什么时候会用到 ssh-agent ?

当你已经将服务器对应的密钥和密码添加到 ssh-agent中,此时使用 SSH 登陆其他服务器时 ssh-agent 就会自动选择对应的是身份密钥和密钥密码进行身份验证。你只需要输入:

1
ssh username@ip地址

Why—为什么要使用 ssh-agent ?

SSH-Agent代理程序可以让我们默认使用密钥登录其他服务器,而无需再次输入密码或 passphrases 。这实现了单点登录(SSO)的形式。

How—如何使用 ssh-agent ?

[^注]:下述命令均基于 CentOS 7

启动ssh-agent

它有两种启动方式,使用前需要确保你已经安装了 openssh ,最小化安装的系统需要安装依赖:

1
yum install openssh-clients

1、ssh-agent $SHELL

它会在当前的 shell 中启动一个子 shell,ssh-agent 程序运行在这个子 shell 中,在 centos 中,$SEHLL 就是 bash。运行后可通过 pstree 命令来查看进程树:

1
2
3
4
5
6
7
[root@localhost ~] ssh-agent bash
[root@localhost ~] pstree
systemd─┬─VGAuthService
├─sshd───sshd───bash───bash─┬─pstree
│ └─ssh-agent

[root@localhost ~] yum -y install psmisc # 如果没有 pstree 命令需要安装

此时就已经进入到了子 shell 中了,ssh-agent 也运行在这里,当我们退出当前的子 shell,ssh-agent 进程也会随之消失。

1
2
3
4
5
[root@localhost ~] exit
exit
[root@localhost ~] pstree
systemd─┬─VGAuthService
├─sshd───sshd───bash───pstree

2、eval ’ssh-agent‘

它会在当前 sheel 直接开启一个 ssh-agent 进程,并返回一个 PID 。

1
2
3
4
5
6
[root@localhost ~] eval `ssh-agent`
Agent pid 30406
[root@localhost ~] pstree
systemd─┬─VGAuthService
├─ssh-agent
├─sshd───sshd───bash───pstree

此时即使退出当前 shell 连接,ssh-agent 进程依然存在。需要使用 ssh-agent -k 命令关闭该进程,如果当前的 shell 意外断开了,就只能通过 kill 命令来停止了:

1
2
3
4
5
6
7
8
9
[root@localhost ~] ssh-agent -k
unset SSH_AUTH_SOCK;
unset SSH_AGENT_PID;
echo Agent pid 30406 killed;

[root@localhost ~] ps -ef | grep ssh-agent
root 30406 1 0 20:01 ? 00:00:00 ssh-agent
root 30549 30494 0 20:01 pts/0 00:00:00 grep --color=auto ssh-agent
[root@localhost ~] kill -9 30406

将私钥添加到 ssh-agent

这里我们在 ostack01 上提前生成了三对密钥,并远程安装至服务器 ostack02(不会的可以参考 为SSH设置密钥登录),它们之间的关系如下:

密钥名称 密钥密码 对应服务器 对应账户
id_rsa root123 ostack02:192.168.60.143 root
id_rsa_empty ostack02:192.168.60.143 user
id_rsa_admin admin123 ostack02:192.168.60.143 admin

此时我们分别使用三个密钥去免密登录 ostack02 的三个账户,你就会发现:

1
2
3
ssh root@192.168.60.143
ssh -i /root/.ssh/id_rsa_empty user@192.168.60.143
ssh -i /root/.ssh/id_rsa_admin admin@192.168.60.143
  • 每次登录 root 用户时还需要输入密钥密码
  • 每次登录 user 用户时还需要手动指定私钥
  • 每次登录 admin 用户时不仅需要指定私钥,还要输入密钥密码-*

为什么使用了密钥之后登录服务器反而更加麻烦了?尤其当主机或账户过多时,每次登录都需要输入私钥密码,极其繁琐。此时,就需要用到 ssh-agent 了:

[注]:需要保证 ssh-agent 已经运行,否则使用 ssh-add 命令会报错。

1
2
3
4
5
6
7
8
9
10
[root@ostack01 .ssh] ssh-add /root/.ssh/id_rsa
Enter passphrase for /root/.ssh/id_rsa:
Identity added: /root/.ssh/id_rsa (/root/.ssh/id_rsa)

[root@ostack01 .ssh] ssh-add /root/.ssh/id_rsa_empty
Identity added: /root/.ssh/id_rsa_empty (/root/.ssh/id_rsa_empty)

[root@ostack01 .ssh] ssh-add /root/.ssh/id_rsa_admin
Enter passphrase for /root/.ssh/id_rsa_admin:
Identity added: /root/.ssh/id_rsa_admin (/root/.ssh/id_rsa_admin)

使用密钥登录服务器

SSH-Agent 可以帮我们管理密钥,在一个 SSH 会话中,只需要在添加时输入一次私钥密码,之后再次连接该服务器时则无需输入密钥密码即可成功登入:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
[root@ostack01 .ssh] ssh root@192.168.60.143
Last login: Mon Jun 15 00:36:23 2020 from 192.168.60.139
[root@ostack02 ~] exit
logout
Connection to 192.168.60.143 closed.

[root@ostack01 .ssh] ssh -i /root/.ssh/id_rsa_empty user@192.168.60.143
Last login: Mon Jun 15 00:36:17 2020 from 192.168.60.139
[user@ostack02 ~]$ exit
logout
Connection to 192.168.60.143 closed.

[root@ostack01 .ssh] ssh -i /root/.ssh/id_rsa_admin admin@192.168.60.143
Last login: Mon Jun 15 00:38:18 2020 from 192.168.60.139
[admin@ostack02 ~]$ exit
logout
Connection to 192.168.60.143 closed.

由此可见 ssh-agent可以帮助我们免去重复输入私钥密码的操作,但还是需要指定密钥。

常用命令

最后总结一下常用的命令:

ssh-agent 常用命令:

1
2
3
4
5
6
7
8
9
10
11
usage: ssh-agent [-c | -s] [-Dd] [-a bind_address] [-E fingerprint_hash]
[-P pkcs11_whitelist] [-t life] [command [arg ...]]
ssh-agent [-c | -s] -k
Options:
-a bind_address 强制将 Unix 域套接字绑定到给定的文件路径,而不是默认套接字
-c 强制在标准输出上生成 C-shell 命令。默认情况下,会自动检测到 shell
-d 启用调试模式
-E fingerprint_hash 指定用于生成 SSH 密钥的算法。有效值包括md5和sha256。
-k 杀死当前正在运行的 ssh-agent 进程
-s 强制/bin/sh在标准输出上生成 Bourne shell 命令。默认情况下,会自动检测 shell
-t life 指定密钥在 ssh-agent 中的有效期。默认将密钥保留在其内存中

ssh-add 常用命令:

1
2
3
4
5
6
7
8
usage: ssh-add [options] [file ...]
Options:
-l 查看 ssh-agent 已经添加的私钥
-L 查看ssh-agent已经添加的私钥对应的公钥
-d 删除指定的私钥
-D 删除所有私钥
-x 锁定 ssh-agent 代理,必须输入密码,加锁后将不再提供任何服务
-X 解锁 ssh-agent 代理,需输入锁定密码