SSH 密钥轮换是安全运维中的重要实践。本文将介绍为什么需要轮换 SSH 密钥,以及如何实现安全、便捷的密钥轮换方案。
为什么要轮换 SSH 密钥#
长期使用同一个 SSH 密钥会带来以下风险:
- 密钥泄露风险:密钥可能通过各种途径泄露(备份泄漏、离职人员带走等)
- 密钥老化:长时间使用的密钥可能被暴力破解或通过其他方式破解
- 合规要求:许多安全标准和合规要求强制定期更换认证凭据
- 最小权限原则:定期轮换可以确保只有当前需要访问的用户持有有效密钥
手动轮换流程#
1. 生成新密钥#
1
2
3
4
5
|
# 使用 Ed25519 算法(推荐)
ssh-keygen -t ed25519 -f ~/.ssh/id_ed25519_new -C "your-email@example.com"
# 或使用 RSA(如果需要兼容旧系统)
ssh-keygen -t rsa -b 4096 -f ~/.ssh/id_rsa_new -C "your-email@example.com"
|
2. 分发公钥到服务器#
1
2
3
4
5
6
7
|
# 方式一:使用 ssh-copy-id
ssh-copy-id -i ~/.ssh/id_ed25519_new.pub user@server
# 方式二:手动添加到远程服务器的 authorized_keys
ssh user@server "mkdir -p ~/.ssh && chmod 700 ~/.ssh"
scp ~/.ssh/id_ed25519_new.pub user@server:~/.ssh/
ssh user@server "cat ~/.ssh/id_ed25519.pub >> ~/.ssh/authorized_keys && chmod 600 ~/.ssh/authorized_keys"
|
3. 验证新密钥可登录#
1
2
|
# 测试新密钥连接
ssh -i ~/.ssh/id_ed25519_new user@server
|
4. 删除旧密钥#
确认新密钥正常工作后,删除旧的公钥和本地私钥:
1
2
3
4
5
|
# 在服务器上删除旧公钥
ssh user@server "sed -i '/old-key-comment/d' ~/.ssh/authorized_keys"
# 本地删除旧私钥
rm ~/.ssh/id_rsa_old ~/.ssh/id_rsa_old.pub
|
使用 SSH 证书实现自动轮换#
SSH 证书认证是一种更优雅的密钥管理方案。核心思想是引入一个 SSH CA(Certificate Authority),由 CA 签署用户证书,证书可以设置有效期,过期自动失效。
1. 创建 SSH CA#
1
2
|
# 创建 SSH CA 密钥(建议存储在专用机器上)
ssh-keygen -t ed25519 -f /path/to/ssh_ca -C "SSH-CA"
|
这会生成两个文件:
/path/to/ssh_ca - CA 私钥(必须严格保管)
/path/to/ssh_ca.pub - CA 公钥(需要分发到所有服务器)
2. 配置服务器信任 CA#
在每台服务器上,将 CA 公钥添加到 authorized_keys 文件的特殊位置(而不是用户目录下):
1
2
3
4
5
6
7
8
|
# 在服务器的 /etc/ssh/ 目录下创建 CA 公钥目录
sudo mkdir -p /etc/ssh/ca_keys
# 复制 CA 公钥到服务器
sudo cp /path/to/ssh_ca.pub /etc/ssh/ca_keys/
# 编辑 SSH 配置
sudo vim /etc/ssh/sshd_config
|
添加以下配置:
1
|
TrustedUserCAKeys /etc/ssh/ca_keys/ssh_ca.pub
|
重启 SSH 服务:
1
|
sudo systemctl restart sshd
|
3. 签署用户证书#
用户生成密钥后,由 CA 使用私钥签署证书:
1
2
|
# CA 服务器执行:签署用户公钥
ssh-keygen -s /path/to/ssh_ca -I "user-identity" -n username -V "+52w" user_key.pub
|
参数说明:
-s:指定 CA 私钥
-I:证书标识符
-n:允许的用户名(Principals)
-V "+52w":证书有效期(52 周)
执行后会生成 user_key-cert.pub 证书文件。
4. 使用证书登录#
用户需要同时提供私钥和证书:
1
|
ssh -i user_key user_key-cert.pub username@server
|
或者在 SSH 配置中指定:
1
2
3
4
5
|
Host server
User username
HostName server.example.com
IdentityFile ~/.ssh/user_key
CertificateFile ~/.ssh/user_key-cert.pub
|
5. 证书过期自动失效#
证书过期后自动失效,无需手动撤销。通过设置较短的有效期(如 1 周或 1 个月),可以实现"定期自动失效"。
用户只需在证书过期前重新申请签名即可继续使用。
批量轮换脚本#
对于需要管理大量服务器的场景,可以使用脚本自动化密钥轮换。以下是一个完整的轮换脚本示例:
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
|
#!/bin/bash
# SSH 密钥自动轮换脚本
set -e
# 配置参数
SSH_DIR="${HOME}/.ssh"
CA_KEY="/path/to/ca_key" # SSH CA 私钥路径
SERVERS_FILE="/path/to/servers.txt" # 服务器列表文件
KEY_COMMENT="$(whoami)@$(hostname)-$(date +%Y%m%d)"
VALIDITY="52w" # 证书有效期
# 1. 生成新的用户密钥对
echo "正在生成新的 Ed25519 密钥..."
KEY_NAME="id_ed25519_$(date +%Y%m%d)"
ssh-keygen -t ed25519 -f "${SSH_DIR}/${KEY_NAME}" -N "" -C "${KEY_COMMENT}"
# 2. 使用 CA 签署用户公钥生成证书
echo "正在签署用户证书..."
CERT_FILE="${SSH_DIR}/${KEY_NAME}-cert.pub"
ssh-keygen -s "${CA_KEY}" -I "${KEY_COMMENT}" -n "$(whoami)" -V "+${VALIDITY}" \
"${SSH_DIR}/${KEY_NAME}.pub" - > "${CERT_FILE}" || {
echo "证书签署失败"
exit 1
}
# 3. 批量部署证书到服务器
echo "正在部署证书到服务器..."
while read -r server; do
if [[ ! "$server" =~ ^#.*$ ]] && [ -n "$server" ]; then
echo "部署到: $server"
scp "${CERT_FILE}" "${server}:~/.ssh/authorized_keys" 2>/dev/null || \
echo "警告: 部署到 $server 失败"
fi
done < "${SERVERS_FILE}"
# 4. 更新 SSH 配置文件
echo "更新 SSH 配置..."
cat >> "${SSH_DIR}/config" <<EOF
# 新证书配置 - $(date)
IdentityFile ~/.ssh/${KEY_NAME}
CertificateFile ~/.ssh/${KEY_NAME}-cert.pub
EOF
echo "密钥轮换完成!新证书有效期: ${VALIDITY}"
|
使用说明:
-
创建服务器列表文件 servers.txt,每行一个服务器地址:
1
2
3
|
user1@server1.example.com
user2@server2.example.com
# 注释行
|
-
运行脚本:
1
2
|
chmod +x rotate_ssh_key.sh
./rotate_ssh_key.sh
|
最佳实践总结#
| 实践 |
说明 |
| 使用现代算法 |
推荐 Ed25519 或 ECDSA,避免 RSA |
| 保护私钥 |
使用强密码短语加密私钥 |
| 使用证书认证 |
简化多用户、多服务器环境的管理 |
| 设置合理有效期 |
根据安全需求设置证书有效期(建议 1-12 个月) |
| 定期审计 |
定期检查和清理不再使用的 SSH 密钥 |
| 及时吊销 |
员工离职时立即撤销其 SSH 访问权限 |
SSH 密钥轮换是保障系统安全的重要措施。通过采用 SSH 证书认证方案,可以实现:
- 证书过期自动失效,无需手动撤销
- 灵活设置有效期,满足不同安全级别需求
- 简化大规模环境下的密钥管理
结合自动化脚本,可以将密钥轮换的运维成本降到最低。
参考来源