ssh-agent 详解

此博客的配图来自《SSH The Secure Shell 2nd》,内容也是对该书相关章节的总结与一些实验的补充。

ssh 推荐的登录方式是使用私钥登录。但是如果生成私钥的时候,设置了口令/密码(passphrase),每次登录时需要输入口令也很麻烦。可以通过 ssh-agent 来管理私钥,把私钥加载进内存,之后便不用再输入密码。

ssh-agent 代理

ssh-agent 的原理如下图:

用户 Bob 使用 ssh-agent 来管理私钥之后。ssh-agent 会启动一个进程在内存里保存这些私钥。之后每次登录时,ssh 客户端都会跟 ssh-agent 请求是否有目标主机的私钥;如果有,ssh 客户端便能直接登录目标主机。

操作步骤如下:

1、通过 ssh-agent bash 或者 eval `ssh-agent`  (这里是shell 的命令替换符)来启动。

2、通过 ssh-add Identity_Linux 为 ssh-agent 添加私钥。这里的 Identity_Linux 是我的私钥文件。

添加之后,可通过 ssh-add -l 来查看已经添加的私钥。

第一条命令,因为服务器设置了只能使用私钥认证登录,所以直接登录失败了。如果私钥不是放在 ssh 客户端缺省读取的位置或者不是默认的名字,就需要使用 -i 选项显示的指定私钥文件。 在给代理添加私钥时,需要输入一次私钥的口令。准备就绪之后,之后不再指定私钥也不需口令即可登录了。

多进程共享 ssh-agent

上边的步骤保障了当前的 shell 能够使用 ssh-agent 代理的密钥;如果要开多个 shell , 如何共享一个  ssh-agent 进程来保存密钥呢?所以深入的探究一下原理。

eval 命令是对字符串参数进行求值,执行字符串表达的命令。比如 eval "ls -lha" 就等同于直接运行 ls -lha 命令。

直接运行 ssh-agent,输出如下:

原来 eval `ssh-agent` 不过首先启动 ssh-agent 进程,然后为当前 shell 环境设置正确的 SSH_AUTH_SOCK 和 SSH_AGENT_PID 这两个环境变量,便能通过环境变量指定的本地套接字与 ssh-agent 进程取得通信,从而获得被代理的密钥。

所以只要在 ssh-agent 启动之后,保存下这两个值,在之后需要的 shell 里用保存的值设置相应的环境变量即可。

1 里将 ssh-agent 启动时的输出记录到文件里,因为此时没有设置正确的环境变量,所以 2 处 ssh-add 无法链接代理。3 处使用 source 命令加载保存的环境变量,所以 4 处能够正常连上。在另外一个 shell 当中重复相同的操作,即图中标注的 5,6,7。8 处添加一个密钥,可以在右边已经连上的 shell 里,看到刚刚添加的密钥,对应第 9 处标注。

整个流程整理成脚本 login.sh,包含 ssh-agent 进程是否启动的检测。逻辑也很简单:如果 ssh-agent 没有启动,在启动的同时将输出记录到文件当中,并且为 ssh-agent 添加有效的密钥;如果已经启动,直接从文件中加载环境变量。

#!/bin/bash

ps | grep ssh-agent > /dev/null
if [ $? -ne 0 ]; then
	echo "ssh-agent is not running, so start it!"
	ssh-agent > ~/ssh_agent_var.sh
	
	source ~/ssh_agent_var.sh

	ssh-add Identity_Linux
else
	echo "ssh-agent is already running!"
	source ~/ssh_agent_var.sh
fi

在 windows 上,开任意个 msys2 终端,都能直接执行脚本,使用一个 ssh-agent 实例进程提供服务。

ssh-agent 代理转发

ssh-agent 代理转发原理如下:

需求:在 X 机器上运行 ssh-agent 代理来管理私钥;通过 X 机器 ssh 登录到 Y 机器;能让 Y 机器上的 ssh 客户端也能使用到所有 X 机器上的 ssh-agent 所管理的所有私钥。

原理:Y 机器上的 ssh 客户端会跟 Y 机器上 sshd 服务器请求私钥。因为已经从 X 登录到 Y 上,X 的 ssh 客户端和 Y 上的 sshd 服务器连理了一条连接。通过这条连接,请求被转发给了 X 上的 ssh 客户端,最终传递给 X 上的 ssh-agent。请求的结果反向传递回去。

使用 ssh-agent 代理转发功能需要:

1、本节点的 ssh 客户端配置文件(/etc/ssh/ssh_config)添加:

ForwardAgent yes

默认是没有开启的。

2、下一节点的 sshd 服务器配置文件(/etc/ssh/sshd_config)添加:

AllowAgentForwarding yes

默认是开启的,服务器的配置文件更改之后,需要 service sshd restart(systemctl 系统需要 systemctl  restart sshd)。

上边的工作完成之后,在 Y 机器上,使用 ssh-add -l 将能查看到与 X 机器上相同的结果。无论是缺少步骤 1 或者是缺少步骤 2,在 Y 上使用 ssh-add -l 查看私钥,将提示:

 一旦当前节点的 ssh 客户端配置 ForwardAgent yes;下一节点的 sshd 服务器配置 AllowAgentForwarding yes。二者缺一不可。下一节点的 ssh-add 便能看到与当前节点一样的所有被管理的私钥。也即完成代理的向前转发;多次转发形成转发链。

上边操作的机器连接示意图:

 总结

无需提供密码是 ssh-agent 的一个好处。另外:

1、如上边的拓扑结构,可以直接使用 scp 命令将 1.15 上的文件拷贝到 1.237 上,在本机执行 scp [email protected]:/root/test.txt [email protected]:/root。

2、假如 1.237 在墙后,只有 1.15 可访问 1.237;然而为了安全,不能在 1.15 上保存秘钥,便可以使用这种方式——上边的拓扑结构中,只需要本机拥有其他机器的登录私钥;其它机器完全不需要前一节点的私钥。这样,本机可以作为一个堡垒机(bastion)来安全的管理所有的私钥。

3、ssh-add 还有其他选项可用,-d 删除已经添加的私钥;-x 锁定shell等。

4、创建一个小型 shell 脚本项目,项目地址在这里 GitHub - zhouguoqionghai/shell_script_for_server_management

总结 ssh-agent 的功能,输出一个统一管理少量的服务器的shell脚本。

使用使用 sv + 序号来登陆服务器,比如 sv5,脚本内置修改登陆使用的 PS1 命令提示符。

 

猜你喜欢

转载自blog.csdn.net/zhouguoqionghai/article/details/92134462