「OpenSSH」- 创建密钥、免密登录(复制公钥到服务器、ssh-agent)

  CREATED BY JENKINSBOT

问题描述

通常(在刚接触 Linux 系统时),我们能够通过输入帐号密码来登录服务器(基础操作),后来我们又学会通过密钥实现无密码登录服务器的方法,再后来我们又学会分发公钥的正确方法,再再后来我们有学会使用 ssh-agent 来管理密钥,再再再后来……

掌握的知识越多,问题也越多……我们慢慢开始记录这些相关的问题,这也是该笔记的主要内容。

该笔记将记录:在 Linux 中,创建 SSH 密钥并分发公钥到服务器的方法,以及常见问题处理。

解决方案

第一步、创建密钥

执行 ssh-keygen 命令,然后一路

# 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:WryBnMpzdq2ISReQ4ZD94a3oJSpy8sDP3RrZqrDSbtw root@macmini
The key's randomart image is:
+---[RSA 3072]----+
|  .o.            |
|  .o.o.          |
|    +o o         |
|     oo+.        |
|     .=.S        |
|.  .o.=+ +       |
|.= +===.o .      |
|=.@.EB+o .       |
|oOo+++o..        |
+----[SHA256]-----+

密钥文件将保存在 ~/.ssh/ 目录中,id_ras 为公钥,id_rsa.pub 为私钥;

第二步、分发公钥

方法一、手动分发(不推荐)

将 id_ras.pub 文件追加到远程服务器 ~/.ssh/authorized_keys 文件中(或者,写入 authorized_keys2 文件)。

虽然不推荐,但是手动添加注释(使用 # 符号):

# This key is for xxxx.
ssh-dss AAAAB3NzaC1kc3MAAACBAN+NX/rmUk...
# This Key is for zzzz.
ssh-dss AAAAB3NkabJ63dV0P5lDabJ8BwuCND...

方法二、ssh-copy-id(推荐)

命令 ssh-copy-id 分发密钥:

ssh-copy-id "user@hostname"
ssh-copy-id -i "/path/to/id_*.pub" "user@hostname"

如何向其他用户分发公钥?

问题描述:我们拥有ROOT帐号的登录权限,但是我们需要向WWW用户分发公钥,并且我们没有WWW用户的密码。

解决方案:

cat ~/.ssh/id_ras.pub \
    | ssh "root@hostname" "sudo -u www tee -a /home/www/authorized_keys"

第三步、登录服务器

此时,再登录服务器便无需输入密码:

ssh "user@hostname"

# 或者,手动指定私钥文件位置

ssh -i /path/to/id_ras "user@hostname"

ssh-agent

运行 ssh-agent -s 命令,将创建 ssh-agent 进程,并输出需要在 shell 中执行的环境变量。ssh 将使用这些环境变量找到 ssh-agent 进程,并连接 ssh-agent 进程。然后 ssh-agent 将代理 ssh 连接服务器。而连接服务器使用的 ssh 私钥将通过 ssh-add 添加到 ssh-agent 中。

SSH Client (ssh) => SSH Agent (ssh-agent) => SSH Server (sshd)

ssh-agent 存在的目的是为了避免客户端(ssh)或者第三方程序接触私钥。管理员通过 ssh-add 向 ssh-agent 中添加密钥,客户端通过 ssh-agent 来访问服务器。同时,管理员还能设置密钥的失效时间。

简单示例

# source <(ssh-agent -s)
Agent pid 1373063

# echo $SSH_AUTH_SOCK $SSH_AGENT_PID
/run/user/1000/keyring/ssh 1728

# ssh-add .ssh/id_rsa
Identity added: .ssh/id_rsa (.ssh/id_rsa)

# ssh root@hostname
...

启动 ssh-agent 进程

我们的 ssh-agent 进程未运行(在用户登录时,这通常由桌面环境自动启动),因此我们需要启动它。

# source <(ssh-agent -s) >/dev/null

ssh_agent_sock=~/.cache/ssh-agent.sock
ssh_agent_pid=$(pidof ssh-agent)
if [ -z "${ssh_agent_pid}" ]; then
    source <(ssh-agent -s -a $ssh_agent_sock) > /dev/null
fi
export SSH_AUTH_SOCK=$ssh_agent_sock

gnome-keyring-daemon

在 GNOME 中,gnome-keyring-daemon 也提供 SSH Agent 功能,它监听 /run/user/<user id>/keyring/ssh 文件。

所以,能够直接使用 ssh-add 而无需运行 ssh-agent 服务:

# echo $SSH_AUTH_SOCK 
/run/user/1001/keyring/ssh

# echo $SSH_AGENT_PID 
3576

# ssh-add .ssh/id_rsa
Identity added: .ssh/id_rsa (.ssh/id_rsa)

参考文献

ssh-copy-id key to other user than yourself?
authorized_keys
Add comment to existing SSH public key – Server Fault
Howto: auto-start ssh-agent with systemd on Debian Bullseye — Debiania
GNOME/Keyring – ArchWiki
Projects/GnomeKeyring/Ssh – GNOME Wiki!