FAQ-13:SSH 密钥认证失败(Permission denied publickey)
预计阅读时间:18 分钟
📖 目录
问题速查表
| 问题 | 解决章节 |
|---|---|
| 客户端私钥与服务器公钥不匹配 | 第一步:确认正在使用的密钥文件、第二步:确认公钥已正确部署到服务器 |
| ~/.ssh 或 authorized_keys 权限过松 | 第三步:检查文件和目录权限、修复权限问题 |
| sshd 配置限制了密钥认证 | 第四步:检查 SSH 服务端配置、修复 sshd 配置 |
| SELinux 安全上下文错误 | 第六步:检查 SELinux(CentOS/RHEL) |
| 公钥内容复制时格式错误 | 原因分析 |
| 需要重新生成并部署密钥 | 生成新的密钥对并部署 |
Permission denied (publickey) 是 SSH 连接中最常见的认证失败错误。当你尝试通过 SSH 连接到远程服务器时,如果服务器拒绝了你的公钥认证,就会看到这个错误。它是系统管理员和开发者日常工作中最频繁遇到的 SSH 问题之一。
SSH 密钥认证的核心机制是:客户端用私钥对一段数据进行签名,服务器用对应的公钥验证签名。如果服务器的 authorized_keys 文件中没有与客户端私钥匹配的公钥条目,认证就会失败。导致不匹配的原因多种多样:密钥文件错误、权限问题、配置限制、文件格式错误等。
理解 SSH 密钥认证的工作原理是排查的基础。SSH 协议在认证阶段会依次尝试所有可用的密钥类型,直到找到匹配的密钥或耗尽所有候选。使用 ssh -v 可以看到这个完整的尝试过程,这是排查问题的第一步。
原因分析
密钥文件不匹配是最常见的原因。客户端尝试使用的私钥与服务器 authorized_keys 中存储的公钥不是一对。这可能是因为你有多个密钥对,ssh 客户端默认选择了错误的密钥。
文件和目录权限错误是 SSH 安全机制的一部分。SSH 服务器对 ~/.ssh 目录和 authorized_keys 文件的权限有严格要求。如果权限设置过松(如 group 或 other 有写权限),SSH 会拒绝使用该密钥进行认证,以防止其他用户篡改授权列表。
SSH 服务端配置限制也会导致认证失败。/etc/ssh/sshd_config 中的 PubkeyAuthentication、AuthorizedKeysFile、PermitRootLogin 等配置项都可能阻止密钥认证。
SELinux 安全上下文在 CentOS/RHEL 系统上可能导致 ~/.ssh 目录或 authorized_keys 文件的安全上下文不正确,即使权限数字正确也会被拒绝。
公钥格式错误在部署密钥时偶尔发生。复制公钥内容时可能引入了多余的换行、空格或字符,导致服务器无法正确解析。
多用户环境下的 HOME 目录权限也需要注意。如果用户的 HOME 目录(如 /home/username)对 group 或 other 有写权限,SSH 同样会拒绝认证。
排查决策树
publickey 认证失败的原因集中在五个层面,按下面的决策树从客户端到服务端逐层排查,不要一开始就去改 sshd 配置:
Permission denied (publickey)
│
├─ ① 客户端侧:确认用的是哪把密钥
│ │ ssh -v user@host 2>&1 | grep "Offering public key"
│ │ ├─ 尝试的不是预期密钥 → 用 -i 指定,或在 ~/.ssh/config
│ │ │ 配 IdentityFile + IdentitiesOnly yes
│ │ └─ 密钥正确 → 进入 ②
│
├─ ② 服务器侧:公钥是否在 authorized_keys 中
│ │ cat ~/.ssh/authorized_keys 与本地 .pub 逐字符比对
│ │ ├─ 缺失 / 复制时换行损坏 → ssh-copy-id 重新部署
│ │ └─ 公钥在 → 进入 ③
│
├─ ③ 权限检查(最常见误配点)
│ │ 基线:~ 755、~/.ssh 700、authorized_keys 600
│ │ ├─ 权限过松 → 服务端日志报 bad ownership or modes
│ │ │ → chmod 修复(见解决方案)
│ │ └─ 权限正确 → 进入 ④
│
├─ ④ sshd 配置检查
│ │ grep PubkeyAuthentication / AuthorizedKeysFile / StrictModes
│ │ ├─ 被禁用或被 sshd_config.d/ 覆盖 → 修正并重启 sshd
│ │ └─ 配置正常 → 进入 ⑤
│
└─ ⑤ SELinux(CentOS/RHEL)
│ ls -Z ~/.ssh/authorized_keys 应为 ssh_home_t
├─ 上下文错误 → restorecon -Rv ~/.ssh
└─ 正常 → 回到 ②,用 ssh -vvv 抓完整认证过程日志
排查步骤
第一步:确认正在使用的密钥文件
# 使用 verbose 模式查看认证过程
ssh -v user@host 2>&1 | grep "Offering public key"
# 输出示例:
# debug1: Offering public key: /home/user/.ssh/id_rsa RSA
# debug1: Offering public key: /home/user/.ssh/id_ed25519 ED25519
# 确认这是你期望使用的密钥文件
# 注意 "Accepted" 和 "Offering" 的区别
第二步:确认公钥已正确部署到服务器
# 在服务器上查看 authorized_keys
cat ~/.ssh/authorized_keys
# 对比本地公钥内容
cat ~/.ssh/id_rsa.pub
# 部署公钥(如果还没部署)
ssh-copy-id user@host
# 手动部署公钥
cat ~/.ssh/id_rsa.pub | ssh user@host "mkdir -p ~/.ssh && cat >> ~/.ssh/authorized_keys"
第三步:检查文件和目录权限
SSH 对权限要求非常严格,以下是正确的权限设置:
# 服务端检查
chmod 700 ~/.ssh
chmod 600 ~/.ssh/authorized_keys
chmod 755 ~ # HOME 目录权限
# 客户端检查
chmod 600 ~/.ssh/id_rsa # 私钥
chmod 644 ~/.ssh/id_rsa.pub # 公钥
chmod 700 ~/.ssh
# 一键修复脚本
chmod 700 ~/.ssh
chmod 600 ~/.ssh/id_* 2>/dev/null
chmod 644 ~/.ssh/*.pub 2>/dev/null
chmod 600 ~/.ssh/authorized_keys 2>/dev/null
chmod 600 ~/.ssh/config 2>/dev/null
第四步:检查 SSH 服务端配置
# 检查关键配置项
grep -E "^PubkeyAuthentication|^AuthorizedKeysFile|^PermitRootLogin|^PasswordAuthentication|^StrictModes" /etc/ssh/sshd_config
# 确保以下配置正确
PubkeyAuthentication yes
AuthorizedKeysFile .ssh/authorized_keys
# PasswordAuthentication no # 如果设为 no 且密钥认证也失败,会完全无法登录
# 检查 /etc/ssh/sshd_config.d/ 下的覆盖配置(Debian/Ubuntu)
ls /etc/ssh/sshd_config.d/
cat /etc/ssh/sshd_config.d/*.conf
第五步:查看详细日志
# 在服务端查看 SSH 日志
sudo journalctl -u sshd -n 50 --no-pager
# 或
sudo tail -50 /var/log/auth.log
# 使用更详细的客户端日志(三重 -v)
ssh -vvv user@host 2>&1 | grep -E "debug1.*key|debug1.*public|debug1.*Accepted|Authentication refused"
第六步:检查 SELinux(CentOS/RHEL)
# 查看 SELinux 状态
getenforce
# 修复 .ssh 目录的安全上下文
restorecon -Rv ~/.ssh
# 或手动设置
chcon -R -t ssh_home_t ~/.ssh
解决方案
生成新的密钥对并部署
# 生成 Ed25519 密钥(推荐)
ssh-keygen -t ed25519 -C "your_email@example.com"
# 生成 RSA 4096 位密钥(兼容性更好)
ssh-keygen -t rsa -b 4096 -C "your_email@example.com"
# 部署到服务器
ssh-copy-id -i ~/.ssh/id_ed25519.pub user@host
# 验证连接
ssh -i ~/.ssh/id_ed25519 user@host
修复权限问题
# 服务端执行
chmod 700 ~/.ssh
chmod 600 ~/.ssh/authorized_keys
chmod 755 ~
# CentOS/RHEL 额外步骤
restorecon -Rv ~/.ssh
配置 SSH 客户端使用指定密钥
# 编辑 ~/.ssh/config
Host myserver
HostName 192.168.1.100
User deploy
IdentityFile ~/.ssh/id_ed25519
IdentitiesOnly yes # 只使用指定的密钥
# 或在命令行指定
ssh -i ~/.ssh/id_ed25519 user@host
修复 sshd 配置
# 编辑 /etc/ssh/sshd_config
sudo vim /etc/ssh/sshd_config
# 确保以下配置
PubkeyAuthentication yes
AuthorizedKeysFile .ssh/authorized_keys
# 重启 SSH 服务
sudo systemctl restart sshd
常见错误总结
| 错误日志 | 原因 | 解决方案 |
|---|---|---|
| Authentication refused: bad ownership or modes for directory | ~/.ssh 或 HOME 目录权限过松 | chmod 700 ~/.ssh && chmod 755 ~ |
| No supported authentication methods available | 服务器禁用了公钥认证 | 设置 PubkeyAuthentication yes |
| Failed publickey for user | 公钥内容不匹配 | 重新部署公钥到 authorized_keys |
| Connection closed by remote host | SSH 配置错误或服务崩溃 | 检查 sshd_config 和服务状态 |
| Key rejected by server | SELinux 安全上下文错误 | restorecon -Rv ~/.ssh |
真实案例
案例 A:~/.ssh 目录权限 777,公钥被 sshd 直接忽略
现象:运维在刚配置好的 CentOS 服务器上测试密钥登录,反复失败:
$ ssh deploy@192.168.1.50
deploy@192.168.1.50: Permission denied (publickey)
排查过程:看服务端日志,第一行就给出了明确线索:
$ sudo tail -5 /var/log/secure
Apr 12 09:31:22 srv50 sshd[2318]: Authentication refused: bad ownership or modes for directory /home/deploy/.ssh
Apr 12 09:31:22 srv50 sshd[2318]: Failed publickey for deploy from 192.168.1.20 port 54321 ssh2
$ ls -ld ~/.ssh ~/.ssh/authorized_keys
drwxrwxrwx 2 deploy deploy 4096 Apr 12 09:00 /home/deploy/.ssh
-rw------- 1 deploy deploy 389 Apr 12 09:00 /home/deploy/.ssh/authorized_keys
根因:.ssh 目录权限是 777(group 和 other 都有写权限)。sshd 的 StrictModes 机制认为该目录可能被其他用户篡改,直接拒绝使用其中的 authorized_keys,日志中的 bad ownership or modes 就是它的"指纹"。
修复:
$ chmod 700 ~/.ssh
$ chmod 600 ~/.ssh/authorized_keys
$ ls -ld ~/.ssh ~/.ssh/authorized_keys
drwx------ 2 deploy deploy 4096 Apr 12 09:10 /home/deploy/.ssh
-rw------- 1 deploy deploy 389 Apr 12 09:10 /home/deploy/.ssh/authorized_keys
验证:
$ ssh deploy@192.168.1.50 # 直接登录成功
Last login: ...
$ sudo tail -2 /var/log/secure
Apr 12 09:31:55 srv50 sshd[2450]: Accepted publickey for deploy from 192.168.1.20 port 54601 ssh2: ED25519 SHA256:...
教训:创建 .ssh 目录后顺手 chmod 700,千万不要用 chmod -R 777 图省事。
案例 B:SELinux 上下文错误导致密钥被拒,restorecon 一键修复
现象:RHEL 8 服务器上,管理员用 rsync 从旧服务器迁移了 /home/user/.ssh 目录,之后密钥登录一直失败:
$ ssh user@192.168.1.60
user@192.168.1.60: Permission denied (publickey)
$ sudo journalctl -u sshd -n 10 --no-pager
sshd[3102]: Failed publickey for user from 192.168.1.20 port 33451 ssh2
排查过程:authorized_keys 内容、权限数字全部正常,怀疑 SELinux。检查安全上下文:
$ getenforce
Enforcing
$ ls -Z ~/.ssh/authorized_keys
unconfined_u:object_r:user_home_t:s0 /home/user/.ssh/authorized_keys
# 正确应为 ssh_home_t
$ sudo ausearch -m avc -ts recent | grep sshd
type=AVC msg=audit(...): avc: denied { read } for pid=3102 comm="sshd"
name="authorized_keys" dev="sda1" ino=... tcontext=user_home_t tclass=file
根因:rsync 迁移的文件带上了错误的安全上下文 user_home_t(应为 ssh_home_t),SELinux 在 Enforcing 模式下拒绝 sshd 读取 authorized_keys,权限数字再正确也没用。
修复:
$ restorecon -Rv ~/.ssh
Relabeled /home/user/.ssh from unconfined_u:object_r:user_home_t:s0 to unconfined_u:object_r:ssh_home_t:s0
Relabeled /home/user/.ssh/authorized_keys from unconfined_u:object_r:user_home_t:s0 to unconfined_u:object_r:ssh_home_t:s0
验证:
$ ssh user@192.168.1.60
Last login: ...
$ ls -Z ~/.ssh/authorized_keys
unconfined_u:object_r:ssh_home_t:s0 /home/user/.ssh/authorized_keys
经验:在 SELinux 系统上用 rsync/scp 迁移 .ssh 目录后,先执行一次 restorecon -Rv ~/.ssh,可以避开绝大多数上下文类故障。
案例 C:sshd_config 禁用密码登录后密钥登录也失败
现象:运维修改 /etc/ssh/sshd_config 禁用密码登录(PasswordAuthentication no),重启 sshd 后所有用户(包括密钥登录)都无法连接。
# 服务端日志
$ sudo journalctl -u sshd -n 10 --no-pager
sshd[4567]: Failed publickey for root from 192.168.1.20 port 54321 ssh2
sshd[4567]: Connection closed by authenticating user root 192.168.1.20 port 54321 [preauth]
# 检查 sshd_config
$ grep -E "^(PubkeyAuthentication|PasswordAuthentication)" /etc/ssh/sshd_config
PubkeyAuthentication no # ← 问题在这里
PasswordAuthentication no
根因:运维在修改配置时误将 PubkeyAuthentication 也设为 no,导致公钥认证被禁用。密码和密钥登录同时被禁,所有用户无法连接。
修复:PubkeyAuthentication yes,然后 sudo systemctl restart sshd。修改 SSH 配置前务必备份:cp /etc/ssh/sshd_config /etc/ssh/sshd_config.bak。
案例 D:多密钥配置导致 ssh 客户端选错密钥
现象:用户有多个 SSH 密钥(工作、个人、服务器),连接某台服务器时报 publickey 拒绝,但用 -i 指定密钥后正常:
# 默认连接失败
$ ssh deploy@server.example.com
deploy@server.example.com: Permission denied (publickey)
# 指定密钥后成功
$ ssh -i ~/.ssh/work_key deploy@server.example.com
Last login: ...
# 查看 ssh 尝试了哪些密钥
$ ssh -v deploy@server.example.com 2>&1 | grep "Offering public key"
debug1: Offering public key: /home/user/.ssh/id_rsa RSA
debug1: Offering public key: /home/user/.ssh/id_ed25519 ED25519
debug1: Offering public key: /home/user/.ssh/personal_key RSA
# 三个密钥都被尝试,但都不匹配
排查过程:
# 查看服务器上允许的公钥
$ ssh deploy@server.example.com "cat ~/.ssh/authorized_keys"
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAA... work-key-comment
# 只有工作密钥在服务器上,但 ssh 默认尝试了其他两个密钥
根因:SSH 客户端默认会尝试 ~/.ssh/ 下的所有密钥。当密钥数量多且服务器只接受特定密钥时,容易出现选错密钥的问题。
修复:配置 ~/.ssh/config 为每个主机指定密钥:
# ~/.ssh/config
Host server.example.com
User deploy
IdentityFile ~/.ssh/work_key
IdentitiesOnly yes # 只使用指定的密钥,不尝试其他
Host github.com
IdentityFile ~/.ssh/personal_key
IdentitiesOnly yes
预防:为每个服务器/服务配置 ~/.ssh/config,明确指定密钥。使用 IdentitiesOnly yes 避免尝试所有密钥。
案例 E:authorized_keys 文件被追加了多余内容
现象:运维手动编辑 authorized_keys 文件后,密钥登录失败:
# 查看 authorized_keys 内容
$ cat ~/.ssh/authorized_keys
# 这是我的工作密钥
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAA... work-key
# 注意这里有个空行
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAA... personal-key
# 末尾有多余的换行符
排查过程:
# 检查文件格式
$ cat -A ~/.ssh/authorized_keys
# 这是我的工作密钥$
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAA... work-key$
$
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAA... personal-key$
$
$
# 查看文件行数
$ wc -l ~/.ssh/authorized_keys
6
根因:authorized_keys 文件中有注释行、空行和多余换行符。虽然 SSH 应该能处理这些格式问题,但某些版本的 sshd 对格式要求更严格。
修复:
# 清理文件,只保留有效的公钥行
$ grep -E "^ssh-" ~/.ssh/authorized_keys > /tmp/keys_clean
$ mv /tmp/keys_clean ~/.ssh/authorized_keys
$ chmod 600 ~/.ssh/authorized_keys
# 验证格式
$ cat -A ~/.ssh/authorized_keys
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAA... work-key$
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAA... personal-key$
预防:使用 ssh-copy-id 部署公钥,避免手动编辑。如需手动编辑,保持每行一个公钥,不要添加注释或空行。
案例 F:HOME 目录权限过松导致整个 SSH 认证链失败
现象:用户执行了 chmod -R 777 ~ 后,SSH 密钥登录完全失败,即使修复了 .ssh 目录权限也无效:
# 修复 .ssh 目录权限后仍然失败
$ chmod 700 ~/.ssh
$ chmod 600 ~/.ssh/authorized_keys
$ ls -ld ~ ~/.ssh ~/.ssh/authorized_keys
drwxrwxrwx 15 user user 4096 Apr 15 10:00 /home/user # HOME 目录仍然是 777
drwx------ 2 user user 4096 Apr 15 10:05 /home/user/.ssh
-rw------- 1 user user 389 Apr 15 10:05 /home/user/.ssh/authorized_keys
$ ssh user@server
user@server: Permission denied (publickey)
排查过程:
# 查看 sshd 日志
$ sudo journalctl -u sshd | grep "bad ownership"
sshd: Authentication refused: bad ownership or modes for home directory /home/user
根因:SSH 的 StrictModes 不仅检查 .ssh 目录权限,还会检查 HOME 目录权限。HOME 目录对 group 或 other 有写权限时,sshd 会拒绝使用该用户的密钥认证。
修复:
# 修复 HOME 目录权限
$ chmod 755 ~
$ ls -ld ~
drwxr-xr-x 15 user user 4096 Apr 15 10:10 /home/user
# 验证连接
$ ssh user@server
Last login: ...
预防:chmod -R 777 ~ 是极其危险的操作,永远不要使用。修改权限时使用精确的权限设置,避免递归修改。
预防措施
- 使用
ssh-copy-id部署公钥,避免手动复制导致的内容错误 - 为不同服务器使用不同密钥对,并在
~/.ssh/config中配置IdentityFile - 使用
ssh-agent管理密钥,避免重复输入私钥密码 - 定期检查服务器的 SSH 配置和权限,尤其是在系统更新后
- 迁移
.ssh目录(rsync/scp)后立即执行restorecon -Rv ~/.ssh(SELinux 系统) - 建立密钥轮换计划:每 6-12 个月轮换一次密钥,定期清理 authorized_keys 中的废弃条目
进阶排查技巧
使用 ssh -vvv 获取详细调试信息
三重 -v 选项可以输出 SSH 连接的完整调试信息:
# 获取完整的认证过程日志
ssh -vvv user@host 2>&1 > /tmp/ssh-debug.log
# 关键信息提取
grep -E "debug1: Offering|debug1: Accepted|debug1: Trying|Authentication refused" /tmp/ssh-debug.log
使用 ssh-keygen 验证密钥对匹配
# 从私钥导出公钥进行比对
ssh-keygen -y -f ~/.ssh/id_ed25519
# 与服务器上的公钥比对
ssh user@host "cat ~/.ssh/authorized_keys"
使用 sshd -T 测试配置
# 测试 sshd 配置文件语法
sudo sshd -t
# 查看 sshd 运行时配置(合并所有配置文件)
sudo sshd -T | grep -E "pubkeyauthentication|authorizedkeysfile|strictmodes"
批量检查服务器 SSH 配置
# 从跳板机批量检查多台服务器的 SSH 配置
for host in server{1..10}; do
echo "=== $host ==="
ssh user@$host "grep -E '^(PubkeyAuthentication|PasswordAuthentication|PermitRootLogin)' /etc/ssh/sshd_config"
done
常见误区与陷阱
- 不要使用
chmod -R 777 ~:这会破坏 SSH 的安全检查,导致密钥认证失败 - 不要在 authorized_keys 中添加注释或空行:虽然 SSH 支持注释,但可能导致解析问题
- 不要忽略 sshd_config.d/ 目录:Debian/Ubuntu 的 SSH 配置可能被该目录下的文件覆盖
- 不要使用 RSA 1024 位密钥:安全性不足,建议使用 Ed25519 或 RSA 4096 位
- 不要在多个服务器间复制同一个密钥对:一个密钥泄露会影响所有服务器
故障复现与验证清单
修复 SSH 密钥认证问题后,使用以下清单验证:
# 1. 验证密钥权限
ls -la ~/.ssh/
# ~/.ssh 目录:700
# 私钥:600
# 公钥:644
# authorized_keys:600
# 2. 验证 HOME 目录权限
ls -ld ~
# 应为 755 或 700
# 3. 验证公钥部署
ssh user@host "cat ~/.ssh/authorized_keys" | grep "your-key-comment"
# 4. 验证 sshd 配置
sudo sshd -T | grep -E "pubkeyauthentication|authorizedkeysfile"
# 5. 验证 SELinux 上下文(CentOS/RHEL)
ls -Z ~/.ssh/authorized_keys
# 应为 ssh_home_t
SSH 权限基线速查表:
| 对象 | 权限 | 说明 |
|---|---|---|
| /home/user(HOME 目录) | 755 或 700 | 组/其他不能有写权限 |
| ~/.ssh | 700 | 仅属主可访问 |
| ~/.ssh/authorized_keys | 600 | 仅属主可读写 |
| ~/.ssh/id_ed25519(私钥) | 600 | 过松 ssh 会拒绝使用 |
| ~/.ssh/id_ed25519.pub(公钥) | 644 | 公钥可公开 |
| ~/.ssh/config | 600 | 可能含敏感参数 |
最佳实践
- 使用 Ed25519 密钥:相比 RSA,Ed25519 密钥更短、更快、更安全,是当前推荐的密钥类型
- 禁用密码登录:部署好密钥认证后,立即禁用
PasswordAuthentication,大幅提升服务器安全性 - 使用 ssh-agent:避免每次连接都输入私钥密码,提升使用体验。运行
ssh-add ~/.ssh/id_ed25519将密钥加入 agent - 维护密钥清单:记录每台服务器使用的密钥对和部署时间,便于后续管理和轮换
- 使用 config 文件:
~/.ssh/config可以为不同服务器配置不同的密钥、用户名、端口,避免每次手动指定
延伸阅读
- 2.11:SSH 深入 SSH 深入——隧道、跳板机与配置管理
- 5.1:Linux 安全加固 Linux 服务器安全加固指南——SSH 最佳实践
- 2.11:SSH 深入 SSH 深入——SSH 密钥认证原理
附录:SSH 密钥管理命令速查表
| 任务 | 命令 | 说明 |
|---|---|---|
| 生成密钥对 | ssh-keygen -t ed25519 | 推荐使用 Ed25519 |
| 部署公钥到服务器 | ssh-copy-id user@host | 自动处理权限和格式 |
| 查看公钥指纹 | ssh-keygen -lf ~/.ssh/id_ed25519.pub | 验证公钥内容 |
| 测试密钥认证 | ssh -v -i 密钥文件 user@host | 查看详细认证过程 |
| 查看 ssh-agent 中的密钥 | ssh-add -l | 列出已加载的密钥 |
| 添加密钥到 agent | ssh-add ~/.ssh/id_ed25519 | 加载私钥到内存 |
| 查看 authorized_keys | cat ~/.ssh/authorized_keys | 检查已部署的公钥 |
| 修复权限 | chmod 700 ~/.ssh && chmod 600 ~/.ssh/authorized_keys | 设置正确权限 |
附录:SSH 配置文件示例
# ~/.ssh/config
# 为不同服务器配置不同的密钥和参数
# 生产服务器
Host prod-server
HostName 192.168.1.100
User deploy
Port 22
IdentityFile ~/.ssh/prod_key
IdentitiesOnly yes
ServerAliveInterval 60
ServerAliveCountMax 3
# 开发服务器(通过跳板机)
Host dev-server
HostName 10.0.0.50
User developer
IdentityFile ~/.ssh/dev_key
ProxyJump jump-server
# 跳板机
Host jump-server
HostName 203.0.113.50
User admin
IdentityFile ~/.ssh/jump_key
Port 2222
# GitHub
Host github.com
HostName github.com
User git
IdentityFile ~/.ssh/github_key
IdentitiesOnly yes
附录:SSH 安全加固清单
- 禁用密码认证:
PasswordAuthentication no - 禁用 root 登录:
PermitRootLogin no - 使用非标准端口(可选,但能减少自动扫描攻击)
- 限制允许登录的用户:
AllowUsers deploy admin - 使用 Fail2ban 防止暴力破解
- 定期轮换密钥(每 6-12 个月)
- 清理 authorized_keys 中的废弃条目
- 监控 SSH 登录日志:
journalctl -u sshd
附录:SSH 调试日志解读
# 使用 ssh -vvv 获取完整调试信息
ssh -vvv user@host 2>&1 | tee /tmp/ssh-debug.log
# 关键日志解读:
# debug1: Offering public key: /home/user/.ssh/id_rsa RSA # 客户端尝试的密钥
# debug1: Server accepts key: /home/user/.ssh/id_rsa RSA # 服务器接受密钥
# debug1: Authentication succeeded (publickey). # 认证成功
# Authentication refused: bad ownership or modes # 权限错误
# debug1: Trying private key: /home/user/.ssh/id_ed25519 # 尝试私钥
#debug1: No more authentication methods to try. # 所有方法失败
附录:SSH 密钥类型对比
| 密钥类型 | 长度 | 安全性 | 性能 | 推荐场景 |
|---|---|---|---|---|
| Ed25519 | 256 位 | 高 | 快 | 首选,适用于所有场景 |
| RSA 4096 | 4096 位 | 高 | 较慢 | 兼容旧系统 |
| RSA 2048 | 2048 位 | 中 | 中等 | 不推荐,安全性不足 |
| ECDSA | 256/384/521 位 | 高 | 快 | 可用于兼容性要求高的场景 |
| DSA | 1024 位 | 低 | 快 | 已弃用,不要使用 |
案例 G:AuthorizedKeysCommand 配置错误导致密钥认证失败
现象:企业环境中使用 AuthorizedKeysCommand 从 LDAP 获取公钥,配置后 SSH 密钥登录失败:
# 服务端日志
$ sudo journalctl -u sshd -n 10 --no-pager
sshd[5678]: AuthorizedKeysCommand /usr/bin/sss_ssh_authorizedkeys failed, status 1
sshd[5678]: Failed publickey for user from 192.168.1.20 port 54321 ssh2
排查过程:
# 检查 sshd 配置
$ grep -E "^(AuthorizedKeysCommand|AuthorizedKeysCommandUser)" /etc/ssh/sshd_config
AuthorizedKeysCommand /usr/bin/sss_ssh_authorizedkeys
AuthorizedKeysCommandUser nobody
# 手动执行命令测试
$ sudo -u nobody /usr/bin/sss_ssh_authorizedkeys user
# 无输出或报错
# 检查 SSSD 状态
$ systemctl status sssd
● sssd.service - System Security Services Daemon
Active: inactive (dead)
根因:AuthorizedKeysCommand 依赖 SSSD 服务从 LDAP 获取公钥,但 SSSD 未运行导致命令执行失败。sshd 在 AuthorizedKeysCommand 失败时会跳过该认证方式,如果本地 authorized_keys 中也没有匹配的公钥,认证就会失败。
修复:
# 启动 SSSD 服务
sudo systemctl start sssd
sudo systemctl enable sssd
# 验证命令可用
sudo -u nobody /usr/bin/sss_ssh_authorizedkeys user
# 测试 SSH 连接
ssh user@host
预防:配置 AuthorizedKeysCommand 后立即测试命令可用性。确保依赖的服务(如 SSSD)已正确配置并设置开机自启。
案例 H:/root HOME 目录权限导致 root 用户 SSH 登录失败
现象:root 用户 SSH 密钥登录失败,但其他用户正常:
# 连接失败
$ ssh root@192.168.1.50
root@192.168.1.50: Permission denied (publickey)
# 检查 root 的 .ssh 目录
$ ls -ld /root /root/.ssh /root/.ssh/authorized_keys
drwx------ 15 root root 4096 Apr 15 10:00 /root
drwx------ 2 root root 4096 Apr 15 10:05 /root/.ssh
-rw------- 1 root root 389 Apr 15 10:05 /root/.ssh/authorized_keys
# 权限看起来正确,但检查 HOME 目录
$ ls -ld /root
drwxr-x--- 15 root root 4096 Apr 15 10:00 /root
# 注意:group 有 rx 权限
根因:SSH 的 StrictModes 检查 HOME 目录权限时,如果 group 有写权限会拒绝认证。某些系统上 /root 目录的 group 权限设置不正确。
修复:
# 修复 HOME 目录权限
$ chmod 700 /root
$ ls -ld /root
drwx------ 15 root root 4096 Apr 15 10:10 /root
# 验证连接
$ ssh root@192.168.1.50
Last login: ...
预防:root 用户的 HOME 目录权限应严格设置为 700。定期检查关键用户的目录权限,尤其是在系统迁移或备份恢复后。
↑ 回到顶部