下面给你一套从排查 → 定位 → 解决的完整流程与命令示例,覆盖 Linux/macOS、Windows(PuTTY/Windows OpenSSH)、常见服务端配置和权限问题。按步骤做,大多数“密钥/公钥连不上服务器”的问题都能被解决。文末有一份速查清单方便演练。


一、先做快速检查(1–2 分钟)

  1. Verbose 模式连一次,看错误信息:
ssh -vvv user@server

注意关键字:debug1: Offering public keydebug1: Authentications that can continuedebug1: Authentication succeeded (publickey)Permission denied (publickey)

  1. 在服务器上查看 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 配置文件,确保 IdentityFileIdentitiesOnly 设置正确:
Host myserver
  HostName server.example.com
  User ubuntu
  IdentityFile ~/.ssh/id_rsa
  IdentitiesOnly yes

2) 公钥没有正确放到服务器(authorized_keys)或格式/换行问题

症状:服务器日志显示找不到公钥或解析失败。

解决:

  • 将本地公钥内容(~/.ssh/id_rsa.pubid_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),也可能导致拒绝。若不确定,设置 700750 再试。

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 推荐 ed25519rsa 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 yesIdentityFile~/.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 窗口顶部 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。

三、专门排查示例(实战命令序列)

按顺序执行,逐步排除问题:

  1. 本地 verbose 尝试(拷贝输出以便分析):
ssh -vvv user@server 2>&amp;1 | tee ssh-debug.log

  1. 确认本地私钥:
ls -l ~/.ssh/
ssh-add -l || ssh-add ~/.ssh/id_rsa

  1. 指定私钥直接尝试:
ssh -i ~/.ssh/id_rsa -o IdentitiesOnly=yes -vvv user@server

  1. 在服务器上检查文件与权限:
# 以 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

  1. 查看服务端日志:
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 failurepublickeykey type 等条目。

  1. 检查 sshd_config:
sudo grep -E "PubkeyAuthentication|AuthorizedKeysFile|StrictModes" /etc/ssh/sshd_config
# 修改后重启
sudo systemctl restart sshd

  1. SELinux 恢复上下文(如适用):
sudo restorecon -Rv /home/user/.ssh

  1. 临时用 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 的配置文件)。

五、快速修复清单(照着做)

  1. 本地:ssh -vvv user@server → 保存输出。
  2. 本地:ssh -i ~/.ssh/id_rsa -o IdentitiesOnly=yes user@server
  3. 服务器:chmod 700 ~/.ssh && chmod 600 ~/.ssh/authorized_keys
  4. 服务器:chown -R user:user ~/.ssh
  5. 服务器:检查 /etc/ssh/sshd_config PubkeyAuthentication yessudo systemctl restart sshd
  6. 如果 SELinux:restorecon -Rv ~/.ssh
  7. 如果 Windows + PuTTY:用 PuTTYgen 生成/转换 .ppk 并把公钥(OpenSSH 格式)粘到 authorized_keys
  8. 如果仍然失败:把 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: passwordno such identity:表示公钥被拒绝,回退到密码或其它方法。
  • Permission denied (publickey):公钥认证被拒绝,常见于权限、格式或未在 authorized_keys 中。