下面给你一套从排查 → 定位 → 解决的完整流程与命令示例,覆盖 Linux/macOS、Windows(PuTTY/Windows OpenSSH)、常见服务端配置和权限问题。按步骤做,大多数“密钥/公钥连不上服务器”的问题都能被解决。文末有一份速查清单方便演练。
一、先做快速检查(1–2 分钟)
- 用Verbose 模式连一次,看错误信息:
ssh -vvv user@server
注意关键字:debug1: Offering public key
、debug1: Authentications that can continue
、debug1: Authentication succeeded (publickey)
、Permission denied (publickey)
- 在服务器上查看 SSH 日志(不同系统路径不同):
# systemd 系统 (CentOS7+/Ubuntu 16.04+)
sudo journalctl -u sshd -e
# Debian/Ubuntu 非 systemd 或历史日志
sudo tail -n 200 /var/log/auth.log
# RHEL/CentOS 6 或类似
sudo tail -n 200 /var/log/secure
在日志中找 publickey
/ authentication
/ sshd
相关错误说明原因。
二、常见原因与解决办法(按优先级)
1) 本地没有用对私钥 / ssh-agent 问题
症状:Offering public key: /home/me/.ssh/id_rsa
后很快收到 no more authentication methods
或未看到 Authentication succeeded
.
解决:
- 明确指定私钥:
ssh -i ~/.ssh/id_rsa user@server
- 检查私钥是否已加入 agent:
ssh-add -l # 列出已加载的 key
ssh-add ~/.ssh/id_rsa
- 如果用的是
ssh
配置文件,确保IdentityFile
与IdentitiesOnly
设置正确:
Host myserver
HostName server.example.com
User ubuntu
IdentityFile ~/.ssh/id_rsa
IdentitiesOnly yes
2) 公钥没有正确放到服务器(authorized_keys)或格式/换行问题
症状:服务器日志显示找不到公钥或解析失败。
解决:
- 将本地公钥内容(
~/.ssh/id_rsa.pub
或id_ed25519.pub
)整行追加到服务器用户的~/.ssh/authorized_keys
:
# 本地
cat ~/.ssh/id_rsa.pub
# 远端(示例,用 ssh-copy-id 自动化)
ssh-copy-id -i ~/.ssh/id_rsa.pub user@server
# 如果 ssh-copy-id 不可用,可用下面方式上传:
cat ~/.ssh/id_rsa.pub | ssh user@server 'mkdir -p ~/.ssh && chmod 700 ~/.ssh && cat >> ~/.ssh/authorized_keys'
- 确保
authorized_keys
中每一行是一把公钥,不要包含额外注释或换行(Windows 的 CRLF 会出问题)。如怀疑行尾问题,服务器上运行:
dos2unix ~/.ssh/authorized_keys
3) 权限(最常见且致命)
SSH 对目录/文件权限非常敏感,权限不当会拒绝公钥验证。
在服务器上(以登录的目标用户或 root)运行:
# 用户家目录权限不应过宽
ls -ld ~
# 推荐:
chmod 700 ~/.ssh
chmod 600 ~/.ssh/authorized_keys
chown -R youruser:yourgroup ~/.ssh
家目录权限通常为 drwxr-xr-x (755)
,若是更松(例如 777),也可能导致拒绝。若不确定,设置 700
或 750
再试。
4) sshd_config 配置问题(服务端)
检查 /etc/ssh/sshd_config
中是否允许公钥认证:
PubkeyAuthentication yes
AuthorizedKeysFile .ssh/authorized_keys
# (可选)
PasswordAuthentication no # 禁用密码,需确保公钥可用
ChallengeResponseAuthentication no
修改后重启 sshd:
sudo systemctl restart sshd # 或 sudo service sshd restart
5) SELinux 或 AppArmor 导致无法读取 authorized_keys
如果服务器启用 SELinux(CentOS/RHEL/Fedora 等),需要检查文件上下文:
# 查看上下文
ls -Z ~/.ssh
# 恢复默认上下文
restorecon -Rv ~/.ssh
AppArmor 也可能限制,检查 /var/log/syslog 或 audit 日志。
6) authorized_keys 中的 options 限制(from=、command=、no-pty 等)
如果 admin 在 authorized_keys
的某行前面添加了 options(例如 from="1.2.3.4"
或 command="..."
),会限制来源或行为,导致无法在其他 IP 或场景下认证。检查是否有这些选项并确认匹配。
7) 密钥类型或算法不匹配(新旧算法/禁用弱算法)
现代 OpenSSH 推荐 ed25519
或 rsa
4096/ecdsa。若服务端禁用了某些算法(例如禁用 rsa-sha1),旧密钥可能被拒绝。解决:
- 生成新密钥(推荐 ed25519):
ssh-keygen -t ed25519 -C "your@comment"
# 或 RSA 4096
ssh-keygen -t rsa -b 4096 -C "your@comment"
- 将新公钥上传到
authorized_keys
。
8) 多 key 干扰 / agent 发送错误 key
当本地有很多 keys,SSH 可能尝试错误的 key 导致服务器拒绝(服务端限制尝试次数)。解决:
- 使用
IdentitiesOnly yes
与IdentityFile
在~/.ssh/config
中指定。 - 或用
-i
明确指定。
9) 连接到错误用户或错误主机
确认使用的是正确的用户名(root 或非 root)和主机名/IP:
ssh user@server # user 必须与服务器上 authorized_keys 所属用户一致
10) Windows + PuTTY 特有问题
- PuTTY 使用
.ppk
格式的私钥。若你只有 OpenSSH 私钥(id_rsa
),需用PuTTYgen
转换:- 打开 PuTTYgen → Load → 选择
id_rsa
→ Save private key(保存为.ppk
)。
- 打开 PuTTYgen → Load → 选择
- 公钥文本要从 PuTTYgen 窗口顶部 copy
Public key for pasting into OpenSSH authorized_keys file
,然后粘到服务器的~/.ssh/authorized_keys
。 - Windows OpenSSH server:authorized_keys 路径为
C:\Users\<user>\.ssh\authorized_keys
,权限也要正确(确保没有 Everyone 写权限)。
11) Firewall / Network / Port 问题(虽少影响公钥但常被忽略)
如果能连上服务器但不到达 sshd,或连上的是其它服务端(例如跳板),会出现认证失败。确认端口、跳板、NAT 转发:
ssh -p 22 user@server
# 或
nmap -p 22 server
telnet server 22
12) Git/CICD / 服务端托管平台
如果你是在 GitHub/GitLab/Bitbucket/CI 上遇到问题:
- 确认公钥已经添加到你的账户或项目。
- 对于 deploy key,检查是否启用了写权限(如果需要 push)。
- 对 SSH agent 在 CI 中使用
ssh-add
并配置 known_hosts。
三、专门排查示例(实战命令序列)
按顺序执行,逐步排除问题:
- 本地 verbose 尝试(拷贝输出以便分析):
ssh -vvv user@server 2>&1 | tee ssh-debug.log
- 确认本地私钥:
ls -l ~/.ssh/
ssh-add -l || ssh-add ~/.ssh/id_rsa
- 指定私钥直接尝试:
ssh -i ~/.ssh/id_rsa -o IdentitiesOnly=yes -vvv user@server
- 在服务器上检查文件与权限:
# 以 root 或能访问该用户的账户检查
sudo su - user
ls -ld ~
ls -ld ~/.ssh
ls -l ~/.ssh/authorized_keys
# 修正权限
chmod 700 ~/.ssh
chmod 600 ~/.ssh/authorized_keys
chown user:user ~/.ssh -R
- 查看服务端日志:
sudo tail -n 200 /var/log/auth.log # Ubuntu/Debian
# 或
sudo tail -n 200 /var/log/secure # RHEL/CentOS
# 或
sudo journalctl -u sshd -e
在日志中查找 authentication failure
、publickey
、key type
等条目。
- 检查 sshd_config:
sudo grep -E "PubkeyAuthentication|AuthorizedKeysFile|StrictModes" /etc/ssh/sshd_config
# 修改后重启
sudo systemctl restart sshd
- SELinux 恢复上下文(如适用):
sudo restorecon -Rv /home/user/.ssh
- 临时用 root 启动 sshd debug(如果可以重启服务并可能影响连接):
sudo /usr/sbin/sshd -d -p 2222 # 在 2222 端口用 debug 模式运行(非后台)
# 然后本地
ssh -p 2222 -i ~/.ssh/id_rsa user@server
这能实时打印服务端为何拒绝公钥。
四、特殊案例提示(常被忽视)
authorized_keys
中公钥被截断或被多余空格造成解析失败。确认整行完整。- 如果
authorized_keys
中有from="ip"
,必须从该 IP 连接或删除该限制。 - 若用 Docker / chroot 或用户家目录在 NFS,权限与 SELinux 可能会阻止读取。
- 若使用
Match
块或自定义sshd_config
规则,可能对某些用户关闭公钥认证。 - 若你用的是云主机提供的镜像(AWS/Azure/GCP),他们有自己的 SSH key 管理机制(不要覆盖 cloud-init 的配置文件)。
五、快速修复清单(照着做)
- 本地:
ssh -vvv user@server
→ 保存输出。 - 本地:
ssh -i ~/.ssh/id_rsa -o IdentitiesOnly=yes user@server
。 - 服务器:
chmod 700 ~/.ssh && chmod 600 ~/.ssh/authorized_keys
。 - 服务器:
chown -R user:user ~/.ssh
。 - 服务器:检查
/etc/ssh/sshd_config
PubkeyAuthentication yes
→sudo systemctl restart sshd
。 - 如果 SELinux:
restorecon -Rv ~/.ssh
。 - 如果 Windows + PuTTY:用 PuTTYgen 生成/转换
.ppk
并把公钥(OpenSSH 格式)粘到authorized_keys
。 - 如果仍然失败:把
ssh -vvv
的输出和/var/log/auth.log
中相关错误贴上来,我帮你分析(可以隐藏敏感部分)。
六、常见 ssh -vvv 关键日志解读(快速说明)
Offering public key: /home/user/.ssh/id_rsa
:客户端已提供私钥对应的公钥。Server accepts key: pkalg ssh-rsa blen 279
:服务端接受该 key(好迹象)。Authentication succeeded (publickey).
:成功。debug1: Authentications that can continue: password
或no such identity
:表示公钥被拒绝,回退到密码或其它方法。Permission denied (publickey)
:公钥认证被拒绝,常见于权限、格式或未在 authorized_keys 中。
发表回复