Linux SSH 免密登录与批量主机管理:从 Passphrase、ssh-agent 到 SSH Config

简介

在 Linux 服务器管理中,SSH 几乎是所有远程运维动作的基础。无论是日常登录服务器、远程执行命令、使用 scp 传输文件,还是通过 rsync 做增量同步,底层通常都依赖 SSH。

最开始接触 SSH 时,我们往往使用最直接的方式:

1
ssh rocky@192.168.0.50

然后输入服务器密码。

这种方式对于一台服务器没有问题,但当需要长期管理多台机器时,问题会很快暴露出来:

1
2
3
4
5
ssh server01 -> 输入密码
ssh server02 -> 输入密码
ssh server03 -> 输入密码
rsync -> 再输入密码
自动脚本 -> 无法交互输入密码

因此,真正适合服务器管理的方案通常会演变成:

1
2
3
4
5
6
7
8
9
SSH 公钥认证

Passphrase 保护私钥

ssh-agent 管理解锁后的私钥

SSH Config 管理主机连接参数

批量 Shell / rsync / Ansible

本文使用如下实验环境进行演示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
本地系统:
macOS

远程系统:
Raspberry Pi
Rocky Linux 9

远程 IP:
192.168.0.50

远程用户:
rocky

SSH 端口:
22

需要特别说明的是,本文不会把 SSH“免密登录”理解成简单地“不要密码”。

更准确地说,它应该叫:

使用 SSH 公钥认证替代远程账户密码认证。

如果进一步给私钥设置 Passphrase,再配合 ssh-agent 和 macOS Keychain,就可以同时兼顾安全性和使用体验。


详解

SSH 密码认证和公钥认证有什么区别

最普通的 SSH 登录方式是:

1
ssh rocky@192.168.0.50

服务器随后要求输入远程用户 rocky 的密码。

其逻辑大致是:

1
2
3
4
5
6
7
8
9
Mac                              Rocky Linux
│ │
│──── 建立 SSH 连接 ───────────────→│
│ │
│←──── 请求身份认证 ────────────────│
│ │
│──── rocky + 用户密码 ────────────→│
│ │
│←──── 登录成功 ────────────────────│

而使用 SSH Key 后,结构变成:

1
2
3
4
5
6
7
8
9
10
Mac
├── 私钥
│ ~/.ssh/id_ed25519_lab_admin

└── 公钥
~/.ssh/id_ed25519_lab_admin.pub


Rocky Linux
└── ~/.ssh/authorized_keys

远程服务器只保存你的公钥。

私钥始终保留在 Mac 上。

连接时并不会把私钥发送给服务器,而是由 SSH 客户端使用私钥对认证数据进行签名,服务器再使用已经保存的公钥验证签名。

可以简单理解为:

1
2
3
4
5
6
7
8
9
10
11
Mac                                Rocky Linux
│ │
│──── 我要以 rocky 身份登录 ─────────→│
│ │
│←──── 证明你持有对应私钥 ────────────│
│ │
│──── 使用私钥完成签名 ──────────────→│
│ │
│ 使用 authorized_keys 验证 │
│ │
│←──────── 验证成功 ─────────────────│

其中有一个非常关键的安全点:

1
2
3
私钥不会发送给服务器
私钥不会通过网络传输
服务器只保存公钥

authorized_keys 是什么

服务器端通常有这样一个文件:

1
~/.ssh/authorized_keys

对于当前实验用户 rocky 来说,实际路径就是:

1
/home/rocky/.ssh/authorized_keys

它的作用可以理解成:

哪些公钥对应的用户有资格登录这个 Linux 账户。

文件内容通常类似:

1
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAA... supermario-mac-lab-admin

如果有多个管理员,则可能存在多行:

1
2
3
ssh-ed25519 AAAA... admin-a
ssh-ed25519 AAAA... admin-b
ssh-ed25519 AAAA... automation

因此,所谓“分发 SSH Key”,实际分发的通常并不是私钥,而是:

1
公钥 -> 远程 ~/.ssh/authorized_keys

known_hosts 又是什么

很多人容易把:

1
authorized_keys

和:

1
known_hosts

混淆。

Mac 上通常存在:

1
~/.ssh/known_hosts

它的作用不是记录“谁可以登录服务器”,而是记录:

我连接过的服务器是谁。

第一次执行:

1
ssh rocky@192.168.0.50

通常会看到:

1
2
The authenticity of host '192.168.0.50' can't be established.
Are you sure you want to continue connecting?

确认后,远程服务器的 Host Key 会记录到:

1
~/.ssh/known_hosts

所以可以这样区分:

1
2
3
4
5
6
7
8
9
authorized_keys

服务器判断:
谁可以登录我?

known_hosts

客户端判断:
我要连接的服务器是不是原来那台?

这意味着 SSH 实际上包含两个不同方向的身份确认。

1
2
3
客户端验证服务器身份
+
服务器验证客户端身份

Passphrase 是什么

创建 SSH Key 时,经常会看到:

1
Enter passphrase:

很多人会直接回车跳过。

但对于管理员使用的 SSH 私钥来说,Passphrase 非常有意义。

假设私钥路径是:

1
~/.ssh/id_ed25519_lab_admin

如果这个文件没有 Passphrase,一旦私钥被别人复制走,对方可能就可以直接:

1
ssh -i id_ed25519_lab_admin rocky@192.168.0.50

如果这把 Key 同时部署到了 50 台服务器,那么风险就变成:

1
2
3
一把私钥泄漏

多台服务器同时失去安全边界

Passphrase 的作用就是:

加密保护磁盘上的私钥文件。

可以用一个不完全严格但非常直观的类比:

1
2
私钥        = 银行卡
Passphrase = 银行卡 PIN

所以:

1
2
3
4
5
6
7
SSH 私钥

证明“我拥有这个身份”

Passphrase

保护“这把私钥本身”

两者解决的不是同一个问题。


为什么设置 Passphrase 后还能做到近似免密

如果私钥设置了 Passphrase,那么直接使用时可能会看到:

1
ssh -i ~/.ssh/id_ed25519_lab_admin rocky@192.168.0.50

提示:

1
Enter passphrase for key '/Users/xxx/.ssh/id_ed25519_lab_admin':

如果每次 SSH、rsync、Git 都重新输入一次 Passphrase,使用体验仍然很差。

因此才有:

1
ssh-agent

ssh-agent 是什么

可以把 ssh-agent 理解成:

内存中的 SSH 私钥代理。

第一次通过:

1
ssh-add ~/.ssh/id_ed25519_lab_admin

将私钥加入 Agent 时,会要求输入一次 Passphrase。

之后:

1
2
3
4
5
私钥解锁

ssh-agent 持有可使用的私钥能力

ssh / rsync / git 调用 ssh-agent 完成签名

其结构类似:

1
2
3
4
5
6
7
8
9
10
11
12
Private Key

│ 第一次输入 Passphrase

┌──────────────┐
│ ssh-agent │
│ 已解锁的 Key │
└──────┬───────┘

┌───┼─────────┐
▼ ▼ ▼
ssh rsync git

ssh-agent 并不是简单地“记住 Passphrase 并自动帮你输入”。

更准确地说,它持有的是已经解锁的密钥能力。

当 SSH 客户端需要签名时:

1
2
3
4
5
6
7
8
9
10
11
12
ssh

│ 请求签名

ssh-agent

│ 使用私钥签名

signature


ssh

这样应用程序本身不需要重新读取并解锁磁盘上的私钥。


macOS Keychain 和 ssh-agent 的关系

macOS 上还可以进一步使用 Apple Keychain。

可以把它们理解成:

1
2
3
4
5
6
7
8
9
Apple Keychain

│ 保存 Passphrase

ssh-agent

│ 管理解锁后的 Key

ssh / rsync / git

添加私钥:

1
ssh-add --apple-use-keychain ~/.ssh/id_ed25519_lab_admin

第一次需要输入 Passphrase。

后续 macOS 可以借助 Keychain 帮助恢复私钥使用状态。

这样最终可以做到:

1
2
3
4
5
6
7
磁盘上的私钥

依然有 Passphrase 加密

日常使用

几乎不用重复输入 Passphrase

这比“创建一个完全没有 Passphrase 的管理员私钥”更加合理。


SSH Config 是什么

如果不使用 SSH Config,连接树莓派可能写成:

1
2
3
4
ssh \
-p 22 \
-i ~/.ssh/id_ed25519_lab_admin \
rocky@192.168.0.50

如果以后服务器越来越多,你需要记忆:

1
2
3
4
5
6
IP
用户名
端口
使用哪把 Key
是否经过跳板机
其他 SSH 参数

SSH Config 就是为了解决这个问题。

默认位置:

1
~/.ssh/config

例如:

1
2
3
4
5
6
Host rocky-pi
HostName 192.168.0.50
User rocky
Port 22
IdentityFile ~/.ssh/id_ed25519_lab_admin
IdentitiesOnly yes

此时:

1
ssh rocky-pi

基本相当于:

1
2
3
4
ssh \
-p 22 \
-i ~/.ssh/id_ed25519_lab_admin \
rocky@192.168.0.50

所以可以把 SSH Config 理解成:

SSH 的服务器连接通讯录。


Host 和 HostName 的区别

例如:

1
2
Host rocky-pi
HostName 192.168.0.50

这里:

1
Host rocky-pi

是自己定义的别名。

而:

1
HostName 192.168.0.50

才是真正连接的服务器地址。

因此:

1
ssh rocky-pi

会先解析:

1
2
3
4
5
rocky-pi

192.168.0.50

rocky@192.168.0.50:22

IdentityFile 是什么

例如:

1
IdentityFile ~/.ssh/id_ed25519_lab_admin

它告诉 SSH:

连接这个 Host 时优先使用哪把私钥。

如果有多个 Key:

1
2
3
4
~/.ssh/id_ed25519_github
~/.ssh/id_ed25519_company
~/.ssh/id_ed25519_lab_admin
~/.ssh/id_ed25519_personal

SSH Config 可以明确指定每台服务器使用哪一把。


IdentitiesOnly yes 是什么

如果 ssh-agent 中存在很多 Key,SSH 客户端可能尝试多个身份。

例如:

1
2
3
4
GitHub Key
公司 Key
实验室 Key
个人服务器 Key

SSH 可能:

1
2
3
4
5
6
7
8
尝试 Key A
失败

尝试 Key B
失败

尝试 Key C
失败

部分服务器会限制认证次数,最终可能出现:

1
Too many authentication failures

配置:

1
2
IdentityFile ~/.ssh/id_ed25519_lab_admin
IdentitiesOnly yes

就是明确告诉 SSH:

这个 Host 只按照我指定的身份文件进行认证,不要自动乱试其他 Key。


AddKeysToAgent 和 UseKeychain

在 macOS 中,可以进一步配置:

1
2
AddKeysToAgent yes
UseKeychain yes

推荐配置:

1
2
3
4
5
6
7
8
Host rocky-pi
HostName 192.168.0.50
User rocky
Port 22
IdentityFile ~/.ssh/id_ed25519_lab_admin
IdentitiesOnly yes
AddKeysToAgent yes
UseKeychain yes

它们可以理解为:

1
2
3
4
5
6
7
8
9
10
11
IdentityFile

使用哪把 Key

AddKeysToAgent

把 Key 加入 ssh-agent

UseKeychain

macOS Keychain 帮助保存和使用 Passphrase

最终日常使用就是:

1
ssh rocky-pi

SSH Config 对 rsync 同样有效

SSH Config 并不只服务于 ssh 命令。

比如:

1
2
3
rsync -avP \
./data/ \
rocky-pi:/home/rocky/data/

rsync 在通过 SSH 连接时,同样会读取:

1
~/.ssh/config

因此无需再写:

1
rsync -e "ssh -i ~/.ssh/id_ed25519_lab_admin -p 22" ...

这也是配置 SSH Config 后非常明显的收益。


多服务器环境怎么理解

假设未来有:

1
2
3
4
192.168.0.50
192.168.0.51
192.168.0.52
192.168.0.60

SSH Config 可以写成:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
Host rocky-pi
HostName 192.168.0.50
User rocky
Port 22
IdentityFile ~/.ssh/id_ed25519_lab_admin
IdentitiesOnly yes

Host app01
HostName 192.168.0.51
User rocky
Port 22
IdentityFile ~/.ssh/id_ed25519_lab_admin
IdentitiesOnly yes

Host app02
HostName 192.168.0.52
User rocky
Port 22
IdentityFile ~/.ssh/id_ed25519_lab_admin
IdentitiesOnly yes

Host mysql01
HostName 192.168.0.60
User rocky
Port 22
IdentityFile ~/.ssh/id_ed25519_lab_admin
IdentitiesOnly yes

之后只需要记:

1
2
3
4
ssh rocky-pi
ssh app01
ssh app02
ssh mysql01

这就是 SSH Config 在服务器管理中的实际价值。


实操实验

实验一:检查当前 SSH 环境

Mac 上查看:

1
ls -la ~/.ssh

可能会看到:

1
2
3
4
id_ed25519
id_ed25519.pub
known_hosts
config

查看当前 ssh-agent 中已经加载的 Key:

1
ssh-add -l

如果没有:

1
The agent has no identities.

说明当前 Agent 中没有已加载的 SSH 私钥。


实验二:为服务器管理创建独立 SSH Key

建议不要随便复用已有的:

1
~/.ssh/id_ed25519

而是创建专门用于实验服务器管理的 Key:

1
2
3
4
5
ssh-keygen \
-t ed25519 \
-a 64 \
-f ~/.ssh/id_ed25519_lab_admin \
-C "supermario-mac-lab-admin"

过程中会提示:

1
2
Enter passphrase:
Enter same passphrase again:

建议设置 Passphrase。

生成:

1
2
~/.ssh/id_ed25519_lab_admin
~/.ssh/id_ed25519_lab_admin.pub

检查:

1
ls -l ~/.ssh/id_ed25519_lab_admin*

其中:

1
id_ed25519_lab_admin

是私钥。

1
id_ed25519_lab_admin.pub

是公钥。

查看公钥:

1
cat ~/.ssh/id_ed25519_lab_admin.pub

私钥不要输出到终端复制、不要上传 Git、不要通过 rsync 分发到服务器。


实验三:手工分发公钥

将公钥写入 Rocky Linux:

1
2
3
4
5
6
7
8
cat ~/.ssh/id_ed25519_lab_admin.pub | \
ssh rocky@192.168.0.50 \
'umask 077;
mkdir -p ~/.ssh;
touch ~/.ssh/authorized_keys;
key=$(cat);
grep -qxF "$key" ~/.ssh/authorized_keys ||
printf "%s\n" "$key" >> ~/.ssh/authorized_keys'

当前仍然需要输入服务器密码。

第一次配置完成后,在服务器检查:

1
ssh rocky@192.168.0.50

然后:

1
cat ~/.ssh/authorized_keys

确认其中存在刚刚添加的:

1
ssh-ed25519 ...

实验四:检查 SSH 文件权限

在 Rocky Linux 上:

1
2
ls -ld ~/.ssh
ls -l ~/.ssh/authorized_keys

推荐权限:

1
2
drwx------ ~/.ssh
-rw------- ~/.ssh/authorized_keys

如果不正确:

1
2
chmod 700 ~/.ssh
chmod 600 ~/.ssh/authorized_keys

确保所有者正确:

1
chown -R rocky:rocky ~/.ssh

Rocky Linux 还启用了 SELinux。

如果文件曾经由 root 手工移动或创建,权限正确但仍然认证失败,可以执行:

1
restorecon -Rv ~/.ssh

实验五:强制验证公钥认证

普通测试:

1
2
3
ssh \
-i ~/.ssh/id_ed25519_lab_admin \
rocky@192.168.0.50

为了确认不是 SSH 自动退回密码认证,可以执行:

1
2
3
4
5
6
7
ssh \
-o BatchMode=yes \
-o PasswordAuthentication=no \
-o IdentitiesOnly=yes \
-i ~/.ssh/id_ed25519_lab_admin \
rocky@192.168.0.50 \
'whoami'

正常输出:

1
rocky

其中:

1
PasswordAuthentication=no

明确禁止使用密码认证。

1
BatchMode=yes

禁止弹出交互式密码输入。

如果仍然成功,就说明 SSH Key 认证真正配置成功。


实验六:将 Key 加入 ssh-agent

执行:

1
ssh-add ~/.ssh/id_ed25519_lab_admin

输入一次 Passphrase。

查看:

1
ssh-add -l

正常可以看到类似:

1
256 SHA256:xxxx... supermario-mac-lab-admin (ED25519)

此时再次:

1
2
3
ssh \
-i ~/.ssh/id_ed25519_lab_admin \
rocky@192.168.0.50

通常不需要重新输入 Passphrase。


实验七:使用 macOS Keychain

在 Mac 上:

1
ssh-add --apple-use-keychain ~/.ssh/id_ed25519_lab_admin

输入一次 Passphrase。

然后创建或者编辑:

1
nano ~/.ssh/config

加入:

1
2
3
4
5
6
7
8
Host rocky-pi
HostName 192.168.0.50
User rocky
Port 22
IdentityFile ~/.ssh/id_ed25519_lab_admin
IdentitiesOnly yes
AddKeysToAgent yes
UseKeychain yes

设置权限:

1
chmod 600 ~/.ssh/config

测试:

1
ssh rocky-pi

如果成功,则 SSH Config、ssh-agent 和 macOS Keychain 已经串联起来。


实验八:查看 SSH 最终解析出来的配置

可以使用:

1
ssh -G rocky-pi

查看 SSH 最终实际使用的配置。

过滤几个重要字段:

1
ssh -G rocky-pi | grep -E '^(hostname|user|port|identityfile|identitiesonly)'

应该看到类似:

1
2
3
4
5
hostname 192.168.0.50
user rocky
port 22
identitiesonly yes
identityfile ~/.ssh/id_ed25519_lab_admin

这个命令对于排查:

1
2
3
4
SSH Config 到底有没有生效
使用的是哪把 Key
端口有没有被覆盖
HostName 到底解析成什么

非常实用。


实验九:查看详细 SSH 认证过程

如果 SSH Key 登录失败:

1
ssh -vvv rocky-pi

其中:

1
2
3
-v
-vv
-vvv

会逐步增加调试信息。

重点关注:

1
2
3
Offering public key
Server accepts key
Authenticated to ...

服务器端可以同时观察:

1
sudo journalctl -u sshd -f

这样可以同时看到客户端和服务端的认证过程。


实验十:使用 SSH Config 简化 rsync

原本:

1
2
3
4
rsync -avP \
-e "ssh -i ~/.ssh/id_ed25519_lab_admin -p 22" \
./data/ \
rocky@192.168.0.50:/home/rocky/data/

配置 SSH Config 后:

1
2
3
rsync -avP \
./data/ \
rocky-pi:/home/rocky/data/

可以看到,SSH Config 不仅简化登录,也可以简化后续所有基于 SSH 的工具。


实验十一:创建批量服务器清单

建立目录:

1
2
mkdir -p ~/ssh-admin
cd ~/ssh-admin

创建:

1
nano hosts.txt

当前只有一台机器:

1
rocky-pi 192.168.0.50 rocky 22

以后可以增加:

1
2
3
4
rocky-pi    192.168.0.50 rocky 22
app01 192.168.0.51 rocky 22
app02 192.168.0.52 rocky 22
mysql01 192.168.0.60 rocky 22

格式:

1
alias host user port

实验十二:批量分发 SSH 公钥

创建:

1
nano distribute-key.sh

写入:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
#!/usr/bin/env bash

set -Eeuo pipefail

INVENTORY="${1:-hosts.txt}"
KEY="${HOME}/.ssh/id_ed25519_lab_admin"
PUB_KEY="${KEY}.pub"

if [[ ! -f "$INVENTORY" ]]; then
echo "ERROR: inventory not found: $INVENTORY"
exit 1
fi

if [[ ! -f "$KEY" || ! -f "$PUB_KEY" ]]; then
echo "ERROR: SSH key does not exist: $KEY"
exit 1
fi

while read -r alias host user port; do

[[ -z "${alias:-}" ]] && continue
[[ "$alias" == \#* ]] && continue

echo "========================================"
echo "Host : $alias"
echo "IP : $host"
echo "User : $user"
echo "Port : $port"
echo "========================================"

if ! ssh \
-p "$port" \
-o ConnectTimeout=5 \
-o StrictHostKeyChecking=accept-new \
"$user@$host" \
'
set -e

umask 077

mkdir -p ~/.ssh
chmod 700 ~/.ssh

touch ~/.ssh/authorized_keys
chmod 600 ~/.ssh/authorized_keys

key=$(cat)

if grep -qxF "$key" ~/.ssh/authorized_keys; then
echo "Public key already exists."
else
printf "%s\n" "$key" >> ~/.ssh/authorized_keys
echo "Public key installed."
fi
' < "$PUB_KEY"
then
echo "ERROR: failed to install key on $alias"
continue
fi

if ssh \
-p "$port" \
-i "$KEY" \
-o BatchMode=yes \
-o PasswordAuthentication=no \
-o IdentitiesOnly=yes \
-o ConnectTimeout=5 \
"$user@$host" \
'printf "SSH KEY AUTH OK - "; hostname; whoami'
then
echo "SUCCESS: $alias"
else
echo "ERROR: key verification failed: $alias"
fi

done < "$INVENTORY"

增加执行权限:

1
chmod +x distribute-key.sh

执行:

1
./distribute-key.sh

这个脚本具备一个很重要的特性:

1
同一把公钥不会被重复追加

实现逻辑:

1
2
grep -qxF "$key" ~/.ssh/authorized_keys ||
printf "%s\n" "$key" >> ~/.ssh/authorized_keys

因此可以重复运行。

这种特性通常称为:

1
2
幂等
idempotent

它也是自动化运维脚本非常重要的设计原则。


实验十三:批量执行 SSH 命令

例如检查所有机器:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
while read -r alias host user port; do

[[ -z "${alias:-}" ]] && continue
[[ "$alias" == \#* ]] && continue

echo "===== $alias ($host) ====="

ssh \
-i ~/.ssh/id_ed25519_lab_admin \
-p "$port" \
-o BatchMode=yes \
-o IdentitiesOnly=yes \
"$user@$host" \
'hostname; uptime'

done < hosts.txt

这已经可以完成非常基础的批量服务器管理。


实验十四:批量 rsync

假设本地目录:

1
~/deploy/

需要同步到所有服务器:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
while read -r alias host user port; do

[[ -z "${alias:-}" ]] && continue
[[ "$alias" == \#* ]] && continue

echo "===== Sync $alias ====="

ssh \
-i ~/.ssh/id_ed25519_lab_admin \
-p "$port" \
-o BatchMode=yes \
-o IdentitiesOnly=yes \
"$user@$host" \
'mkdir -p ~/deploy'

rsync -avP \
-e "ssh -i ${HOME}/.ssh/id_ed25519_lab_admin -p ${port} -o BatchMode=yes -o IdentitiesOnly=yes" \
~/deploy/ \
"$user@$host:/home/$user/deploy/"

done < hosts.txt

整体结构就是:

1
2
3
4
5
6
7
                    ┌──> server01

Mac ── SSH/rsync ───├──> server02

├──> server03

└──> serverN

实验十五:什么时候应该升级到 Ansible

Shell + SSH 非常适合学习 SSH 原理,也适合少量机器。

大致可以这样理解:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
1~5 台

SSH Config + 手工管理

5~20 台

hosts.txt + Shell

20~100 台

Ansible 更合适

更大规模

Ansible
堡垒机
集中身份管理
OpenSSH CA

Shell 脚本适合:

1
2
3
理解底层原理
执行简单批量任务
快速构建自己的管理工具

但机器规模越来越大后,还要解决:

1
2
3
4
5
6
7
8
9
并发
失败重试
变量
权限提升
不同系统差异
配置状态管理
密钥轮换
Secret 管理
执行结果汇总

这正是 Ansible 这类工具存在的意义。


实验十六:理解 OpenSSH CA 的价值

传统 SSH Key 管理是:

1
2
3
4
5
6
7
管理员公钥

server01 authorized_keys
server02 authorized_keys
server03 authorized_keys
...
server100 authorized_keys

如果管理员离职或者私钥泄漏:

1
需要从所有服务器删除对应公钥

服务器数量多以后,这会变得非常麻烦。

OpenSSH CA 的思路则是:

1
2
3
4
5
6
7
8
9
          SSH CA

│ 签发证书

管理员 SSH 证书

┌─────────┼─────────┐
▼ ▼ ▼
server01 server02 serverN

服务器只需要信任 CA:

1
TrustedUserCAKeys

而不需要给每个管理员单独维护大量 authorized_keys

这更加适合大型基础设施。


总结

SSH 免密认证真正应该理解成:

1
使用公钥认证替代远程账户密码认证

而不是简单地“把密码取消”。

一套相对完整的 SSH 管理体系可以理解为:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
SSH Config

告诉 SSH:
连接哪台服务器
使用哪个用户
哪个端口
哪把私钥

ssh-agent

管理已经解锁的私钥

Passphrase

保护磁盘上的私钥文件

authorized_keys

服务器记录允许登录的公钥

known_hosts

客户端记录并验证服务器身份

对于当前 Mac + Raspberry Pi Rocky Linux 9 的实验环境:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
Mac

├── ~/.ssh/id_ed25519_lab_admin
│ 私钥 + Passphrase

├── ssh-agent
│ 管理解锁后的 Key

├── Apple Keychain
│ 保存 Passphrase

└── ~/.ssh/config

│ Host rocky-pi

192.168.0.50
Rocky Linux 9

└── /home/rocky/.ssh/authorized_keys
保存 Mac 的公钥

最终日常登录可以简化为:

1
ssh rocky-pi

rsync 也可以直接:

1
2
3
rsync -avP \
./data/ \
rocky-pi:/home/rocky/data/

学习 SSH 时,建议按照如下顺序逐步深入:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
密码 SSH

单机 SSH 公钥认证

authorized_keys

Passphrase

ssh-agent

macOS Keychain

SSH Config

批量 Shell

批量 rsync

Ansible

OpenSSH CA

理解这条链路之后,SSH 就不再只是一个“远程登录命令”,而会成为后续 Linux 服务器管理、rsync 文件同步、自动部署、Ansible 自动化、堡垒机和大规模主机身份管理的基础设施。


Linux SSH 免密登录与批量主机管理:从 Passphrase、ssh-agent 到 SSH Config
https://allendericdalexander.github.io/2026/09/09/devops/learn/linux-ssh-key-agent-config-rsync-hexo/
作者
AtLuoFu
发布于
2026年9月9日
许可协议