从 “Permission denied” 到 “连接成功”:SSH 进阶排错手册

前言:为什么 “Permission denied” 最难排查?

SSH 登录时的 “Permission denied”(权限拒绝)是最常见的错误,但背后原因却五花八门 —— 可能是密钥权限不对,可能是服务器禁用了密码登录,也可能是 sshd_config 语法错误。新手往往会反复尝试登录,却不知道从日志、权限、配置三个维度入手,导致排查耗时 1-2 小时仍无进展。

本文的核心价值是 建立排错逻辑”:先通过错误日志缩小范围,再按 “客户端→服务器端” 顺序排查,最后用工具验证,确保每一步都有依据,避免盲目尝试。所有步骤均基于 CentOS 8/Ubuntu 22.04 实测,提供可直接执行的命令,覆盖 90% 导致 “Permission denied” 的场景。

一、排错前置:先抓 “关键证据”—— 日志与调试信息

遇到 “Permission denied” 时,不要反复重试登录,先收集两类关键信息,可直接定位 70% 的问题:

1. 客户端调试日志(ssh -v)

通过 ssh -v 查看客户端与服务器的交互过程,重点关注 “认证阶段” 的错误提示:

# 格式:ssh -v [用户@IP/别名] -p [端口]

ssh -v ops@10.0.1.10 -p 2222 2>&1 | grep -E "Permission denied|Failed|error"

关键输出解读
  1. Permission denied (publickey):仅允许密钥认证,客户端未提供有效密钥;
  2. Permission denied (password):仅允许密码认证,客户端密码错误或未输入;
  3. Bad owner or permissions on /home/ops/.ssh/config:客户端配置文件权限错误;
  4. No such file or directory:客户端密钥文件路径错误。

2. 服务器端日志(定位服务端拒绝原因)

服务器端日志记录了 “为什么拒绝登录”,不同系统日志路径不同:

# 1. CentOS/RHEL 系统(日志路径:/var/log/secure

sudo tail -n 20 /var/log/secure | grep sshd

# 2. Ubuntu/Debian 系统(用 journalctl 查看 sshd 服务日志)

sudo journalctl -u sshd --no-pager -n 20

关键日志解读
  1. Bad owner or permissions on /home/ops/.ssh/authorized_keys:服务器端公钥文件权限错误;
  2. Invalid user ops from 192.168.1.10 port 54321:登录用户不存在;
  3. Password authentication failed for user ops:密码错误(服务器允许密码登录时);
  4. Pubkey authentication failed for user ops:公钥认证失败(公钥不匹配或格式错误);
  5. User root from 192.168.1.10 not allowed because PermitRootLogin is set to no:root 登录被禁用。

二、第一类故障:密钥认证相关的 “Permission denied”(4 种场景)

密钥认证是 SSH 登录的主流方式,公钥未上传、格式错误、权限不对均会导致 “Permission denied (publickey)”。

场景 1:客户端公钥未上传到服务器

错误现象
  1. 客户端日志:Permission denied (publickey)
  2. 服务器日志:No more authentication methods to try. ops from 192.168.1.10 port 54321 ssh2
排查步骤
  1. 确认客户端公钥文件存在(默认 ~/.ssh/id_rsa.pub 或自定义密钥的 .pub 文件):

# 客户端执行:查看公钥文件

ls -l ~/.ssh/id_rsa.pub  # 若提示 No such file or directory,说明未生成密钥

  1. 确认服务器端 authorized_keys 中是否有客户端公钥:

# 若能通过密码登录服务器(临时允许),执行:

ssh -o PasswordAuthentication=yes ops@10.0.1.10 "cat ~/.ssh/authorized_keys"

# 对比客户端公钥(输出是否包含客户端 ~/.ssh/id_rsa.pub 的内容)

cat ~/.ssh/id_rsa.pub

解决方案
  1. 客户端生成密钥(若未生成):

ssh-keygen -t ed25519 -C "ops@client"  # 生成 ed25519 密钥(比 RSA 更安全)

# 按回车默认保存到 ~/.ssh/id_ed25519,可选设置密码(passphrase

  1. 上传客户端公钥到服务器:

# 方法1:用 ssh-copy-id 自动上传(推荐,会自动处理权限)

ssh-copy-id -p 2222 ops@10.0.1.10

# 方法2:手动复制(若 ssh-copy-id 不可用)

cat ~/.ssh/id_ed25519.pub | ssh -p 2222 ops@10.0.1.10 "mkdir -p ~/.ssh && cat >> ~/.ssh/authorized_keys"

验证

# 重新用密钥登录,成功则解决

ssh -p 2222 ops@10.0.1.10

场景 2:服务器端 authorized_keys 权限 / 属主错误

错误现象
  1. 客户端日志:Permission denied (publickey)
  2. 服务器日志:Bad owner or permissions on /home/ops/.ssh/authorized_keys
排查步骤
  1. 登录服务器(临时密码登录),查看 authorized_keys 及其父目录 .ssh 的权限和属主:

# 查看 .ssh 目录权限(应是 700,属主为登录用户)

ls -ld ~/.ssh

# 查看 authorized_keys 权限(应是 600,属主为登录用户)

ls -l ~/.ssh/authorized_keys

  1. 常见错误权限:
    1. .ssh 目录权限为 755(其他用户可进入);
    2. authorized_keys 权限为 644(其他用户可读);
    3. 属主为 root(非登录用户)。
解决方案

# 修复 .ssh 目录权限(700)和属主

chmod 700 ~/.ssh

chown ops:ops ~/.ssh  # 替换 ops 为实际登录用户

# 修复 authorized_keys 权限(600)和属主

chmod 600 ~/.ssh/authorized_keys

chown ops:ops ~/.ssh/authorized_keys

验证

# 重新登录,若日志无 Bad permissions 提示,说明解决

ssh -v -p 2222 ops@10.0.1.10 2>&1 | grep "Bad permissions"

# 无输出则正常

场景 3:客户端密钥权限过宽

错误现象
  1. 客户端日志:Permissions 0644 for '/home/ops/.ssh/id_ed25519' are too open
  2. 后续提示:Permission denied (publickey)
排查步骤
  1. 客户端查看密钥文件权限:

ls -l ~/.ssh/id_ed25519  # 若输出 -rw-r--r--644),则权限过宽

  1. SSH 要求私钥文件必须是 600(仅当前用户可读写),权限过宽会被判定为 “密钥泄露风险”,直接拒绝使用。
解决方案

# 修复客户端密钥权限(600

chmod 600 ~/.ssh/id_ed25519

# 若有多个密钥,批量修复

chmod 600 ~/.ssh/id_*  # 注意:仅私钥文件,公钥 .pub 可保留 644

验证

# 重新登录,无 Permissions are too open 提示则正常

ssh -p 2222 ops@10.0.1.10

场景 4:公钥格式错误或不完整

错误现象
  1. 客户端日志:Permission denied (publickey)
  2. 服务器日志:Invalid key data in /home/ops/.ssh/authorized_keys: 1(第 1 行公钥无效)。
排查步骤
  1. 客户端查看公钥格式(以 ed25519 为例,应是一行完整字符串):

cat ~/.ssh/id_ed25519.pub

# 正确格式:ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIL... ops@client

  1. 常见格式错误:
    1. 公钥被换行拆分(多行);
    2. 末尾注释包含特殊字符(如中文、空格);
    3. 复制时遗漏开头 ssh-ed25519 或末尾注释。
解决方案
  1. 客户端重新复制完整公钥:

# cat 输出并复制,避免手动换行

cat ~/.ssh/id_ed25519.pub

  1. 服务器端替换错误公钥:

# 登录服务器,编辑 authorized_keys,删除错误行,粘贴正确公钥

vim ~/.ssh/authorized_keys

# 确保正确公钥是一行完整内容,无换行

验证

# 服务器端验证公钥格式(无报错则正常)

ssh-keygen -l -f ~/.ssh/authorized_keys

# 输出类似:256 SHA256:xxxx ops@client (ED25519)

二、第二类故障:认证方式配置导致的 “Permission denied”(3 种场景)

服务器端 sshd_config 中关于 “认证方式” 的配置(如禁用密码、禁止 root 登录),是导致 “Permission denied” 的高频原因。

场景 5:服务器禁用密码登录(PasswordAuthentication no)

错误现象
  1. 客户端日志:Permission denied (publickey)
  2. 若客户端尝试密码登录,提示:No supported authentication methods available
排查步骤
  1. 查看服务器端 sshd_configPasswordAuthentication 配置:

# 登录服务器(若能通过密钥登录),执行:

sudo grep -i "PasswordAuthentication" /etc/ssh/sshd_config

# 若输出 PasswordAuthentication no,说明禁用密码登录

  1. 错误场景:客户端未上传公钥,却尝试用密码登录,服务器仅允许密钥认证,导致拒绝。
解决方案

根据需求二选一:

  1. 方案 1:启用密码登录(临时调试)

sudo vim /etc/ssh/sshd_config

# 修改为:

PasswordAuthentication yes

# 测试配置语法并重启服务

sudo sshd -t

sudo systemctl restart sshd

# 此时可通过密码登录,再上传公钥

  1. 方案 2:上传公钥(推荐,安全)

参考 “场景 1” 的公钥上传步骤,确保客户端公钥已在服务器 authorized_keys 中。

验证

# 方案 1 验证:密码登录成功

ssh -o PreferredAuthentications=password -p 2222 ops@10.0.1.10

# 方案 2 验证:密钥登录成功

ssh -p 2222 ops@10.0.1.10

场景 6:禁止 root 用户登录(PermitRootLogin no)

错误现象
  1. 客户端日志:Permission denied, please try again.
  2. 服务器日志:User root from 192.168.1.10 not allowed because PermitRootLogin is set to no
排查步骤
  1. 确认客户端登录用户是 root:

# 客户端登录命令(若包含 root@

ssh root@10.0.1.10  # 此时服务器禁止 root 登录

  1. 查看服务器端 PermitRootLogin 配置:

sudo grep -i "PermitRootLogin" /etc/ssh/sshd_config

# 若输出 PermitRootLogin no,说明禁止 root 直接登录

解决方案

根据安全需求选择:

  1. 方案 1:用普通用户登录后提权(推荐,安全)

# 客户端用普通用户 ops 登录

ssh ops@10.0.1.10

# 登录后用 sudo 提权(需 ops sudoers 中)

sudo -i  # 切换到 root

  1. 方案 2:临时允许 root 登录(不推荐,仅调试)

sudo vim /etc/ssh/sshd_config

# 修改为:

PermitRootLogin yes

# 测试语法并重启服务

sudo sshd -t

sudo systemctl restart sshd

# 此时 root 可登录,调试后建议改回 no

验证

# 方案 1 验证:普通用户登录成功并提权

ssh ops@10.0.1.10 "sudo whoami"  # 输出 root 则正常

# 方案 2 验证:root 登录成功

ssh root@10.0.1.10

场景 7:服务器限制登录用户(AllowUsers/AllowGroups)

错误现象
  1. 客户端日志:Permission denied, please try again.
  2. 服务器日志:User test from 192.168.1.10 not allowed because not listed in AllowUsers
排查步骤
  1. 查看服务器端 AllowUsersAllowGroups 配置:

sudo grep -i "AllowUsers" /etc/ssh/sshd_config

sudo grep -i "AllowGroups" /etc/ssh/sshd_config

  1. 常见限制:
    1. AllowUsers ops admin:仅允许 ops 和 admin 登录,test 用户不在列表;
    2. AllowGroups ssh-users:仅允许 ssh-users 组用户登录,test 不在该组。
解决方案
  1. 方案 1:将用户加入 AllowUsers

sudo vim /etc/ssh/sshd_config

# 修改为(添加 test 用户):

AllowUsers ops admin test

# 重启服务

sudo systemctl restart sshd

  1. 方案 2:将用户加入 AllowGroups

# 假设 AllowGroups ssh-users,将 test 加入该组

sudo usermod -aG ssh-users test

# 验证用户是否在组中

groups test  # 输出包含 ssh-users 则正常

验证

# 客户端用 test 用户登录,成功则解决

ssh test@10.0.1.10

三、第三类故障:配置文件错误导致的 “Permission denied”(3 种场景)

sshd_config 语法错误、Include 路径错误、客户端 config 配置冲突,会间接导致认证失败,出现 “Permission denied”。

场景 8:服务器端 sshd_config 语法错误

错误现象
  1. 客户端登录提示:Connection closed by 10.0.1.10 port 2222
  2. 服务器端重启 sshd 失败:Job for sshd.service failed
  3. 间接导致登录时无认证方式可选,提示 Permission denied
排查步骤
  1. 测试 sshd_config 语法(核心!语法错误会导致 sshd 加载配置失败):

sudo sshd -t

# 若有错误,会提示具体行号,如:

# /etc/ssh/sshd_config line 56: Bad option: PasswordAuthentiation

  1. 常见语法错误:
    1. 参数拼写错误(如 PasswordAuthentiation 少写一个 c);
    2. 参数值错误(如 PermitRootLogin 0,应为 yes/no);
    3. 多余符号(如行尾多一个分号 ;)。
解决方案
  1. 根据 sshd -t 提示修改错误行:

# 编辑 sshd_config,定位错误行(如 line 56

sudo vim +56 /etc/ssh/sshd_config

# 修正拼写错误,如 PasswordAuthentiation → PasswordAuthentication

  1. 测试语法无误后重启服务:

sudo sshd -t  # 无输出则语法正确

sudo systemctl restart sshd

验证

# 客户端重新登录,若能正常进入认证阶段,说明解决

ssh -v ops@10.0.1.10

场景 9:客户端 ~/.ssh/config 权限过宽

错误现象
  1. 客户端登录提示:Bad owner or permissions on /home/ops/.ssh/config
  2. 后续无法加载配置,默认用密码登录,若服务器禁用密码,则提示 Permission denied
排查步骤
  1. 客户端查看 config 文件权限:

ls -l ~/.ssh/config

# 若输出 -rw-r--r--644)或 -rwxr-xr-x755),则权限过宽

  1. SSH 要求 config 文件权限必须是 600(仅当前用户可读写),防止他人篡改配置(如修改密钥路径)。
解决方案

# 修复 config 文件权限(600

chmod 600 ~/.ssh/config

验证

# 重新登录,无 Bad owner or permissions 提示,且能加载配置

ssh -v prod-web 2>&1 | grep "config"

# 输出类似 "Reading configuration data /home/ops/.ssh/config" 则正常

场景 10:客户端 config 配置冲突(密钥路径错误)

错误现象
  1. 客户端日志:Permission denied (publickey)
  2. 调试日志显示:Offering public key: /home/ops/.ssh/id_rsa(实际密钥是 id_ed25519)。
排查步骤
  1. 查看客户端 configIdentityFile 配置:

grep -i "IdentityFile" ~/.ssh/config

# 若输出 IdentityFile ~/.ssh/id_rsa,而实际密钥是 id_ed25519,则路径错误

  1. 配置冲突导致客户端提供错误的密钥,服务器拒绝,出现 Permission denied
解决方案
  1. 修改 config 中的 IdentityFile 为正确路径:

vim ~/.ssh/config

# 修改为:

IdentityFile ~/.ssh/id_ed25519

  1. 若用别名登录,确保别名配置正确:

# 示例:prod-web 别名配置

Host prod-web

  HostName 10.0.1.10

  User ops

  Port 2222

  IdentityFile ~/.ssh/id_ed25519  # 正确密钥路径

验证

# 用别名登录,调试日志显示正确密钥路径则正常

ssh -v prod-web 2>&1 | grep "Offering public key"

# 输出 "Offering public key: /home/ops/.ssh/id_ed25519" 则正确

四、进阶排错:用工具快速定位问题(3 个核心工具)

当常规排查无效时,以下工具可帮助你 “穿透” 认证流程,定位隐藏问题。

1. sshd -T:查看服务器端生效的完整配置

# 服务器端执行,查看所有生效的 sshd 配置(排除注释和默认值)

sudo sshd -T | grep -i "passwordauthentication\|permitrootlogin\|allowusers"

# 输出示例:

# passwordauthentication no

# permitrootlogin no

# allowusers ops admin

# 可快速确认配置是否真的生效(避免 Include 路径错误导致配置未加载)

2. ssh-keyscan:验证服务器端主机密钥

若客户端 known_hosts 中存储的服务器主机密钥与实际不符,会拒绝连接,间接导致 Permission denied

# 客户端执行,获取服务器当前主机密钥

ssh-keyscan -p 2222 10.0.1.10

# 对比客户端 known_hosts 中的密钥(删除旧密钥,重新登录)

sed -i "/10.0.1.10/d" ~/.ssh/known_hosts

ssh ops@10.0.1.10  # 重新接受新密钥

3. journalctl -u sshd -f:实时监控服务器端日志

登录时实时查看服务器端日志,捕捉瞬间的错误信息:

# 服务器端执行,实时监控

sudo journalctl -u sshd -f

# 客户端同时尝试登录,观察日志输出,定位拒绝原因

五、排错流程图:从 “Permission denied” 到 “连接成功” 的步骤总结

flowchart TD

    A[遇到 Permission denied] --> B[客户端执行 ssh -v 查看调试日志]

    B --> C{日志关键词}

    C -->|publickey| D[排查密钥相关问题]

    C -->|password| E[排查密码认证问题]

    C -->|Bad permissions| F[排查文件权限问题]

    C -->|not allowed| G[排查 AllowUsers/AllowGroups]

   

    D --> D1[客户端密钥权限是否 600]

    D1 -->|| D1a[chmod 600 密钥]

    D1 -->|| D2[服务器端 authorized_keys 是否有客户端公钥?]

    D2 -->|| D2a[ssh-copy-id 上传公钥]

    D2 -->|| D3[服务器端 .ssh/authorized_keys 权限是否 700/600]

    D3 -->|| D3a[chmod 700 .ssh; chmod 600 authorized_keys]

    D3 -->|| D4[公钥格式是否完整?]

    D4 -->|| D4a[重新复制完整公钥]

    D4 -->|| Z[连接成功]

   

    E --> E1[服务器端 PasswordAuthentication 是否 yes]

    E1 -->|| E1a[临时启用 PasswordAuthentication yes]

    E1 -->|| E2[密码是否正确?]

    E2 -->|| E2a[重置密码:passwd 用户名]

    E2 -->|| Z[连接成功]

   

    F --> F1[客户端 config/密钥权限是否 600]

    F1 -->|| F1a[chmod 600 对应文件]

    F1 -->|| F2[服务器端 .ssh/authorized_keys 权限是否 700/600]

    F2 -->|| F2a[chmod 700 .ssh; chmod 600 authorized_keys]

    F2 -->|| Z[连接成功]

   

    G --> G1[用户是否在 AllowUsers 列表?]

    G1 -->|| G1a[添加用户到 AllowUsers]

    G1 -->|| G2[用户是否在 AllowGroups 组?]

    G2 -->|| G2a[usermod -aG 组名 用户名]

    G2 -->|| Z[连接成功]

总结:排错的 3 个核心原则

  1. 先看日志,再动手:客户端 ssh -v 和服务器端日志是定位问题的 “钥匙”,不要盲目尝试登录;
  2. 先查权限,再查配置:80% 的 “Permission denied” 与权限相关(密钥、.ssh、authorized_keys),优先排查;
  3. 修改前备份,修改后测试:修改 sshd_config 前备份(cp /etc/ssh/sshd_config{,.bak}),用 sshd -t 测试语法,避免改坏后连不上。

按照本文的步骤,你可在 5-10 分钟内定位并解决绝大多数 “Permission denied” 问题,从 “登录失败” 快速过渡到 “连接成功”。若遇到特殊场景(如 LDAP 认证、双因素认证),可结合对应日志进一步排查,或在评论区留言补充!

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐