从 “Permission denied” 到 “连接成功”:SSH 进阶排错手册
从 “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" |
关键输出解读
- Permission denied (publickey):仅允许密钥认证,客户端未提供有效密钥;
- Permission denied (password):仅允许密码认证,客户端密码错误或未输入;
- Bad owner or permissions on /home/ops/.ssh/config:客户端配置文件权限错误;
- 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 |
关键日志解读
- Bad owner or permissions on /home/ops/.ssh/authorized_keys:服务器端公钥文件权限错误;
- Invalid user ops from 192.168.1.10 port 54321:登录用户不存在;
- Password authentication failed for user ops:密码错误(服务器允许密码登录时);
- Pubkey authentication failed for user ops:公钥认证失败(公钥不匹配或格式错误);
- User root from 192.168.1.10 not allowed because PermitRootLogin is set to no:root 登录被禁用。
二、第一类故障:密钥认证相关的 “Permission denied”(4 种场景)
密钥认证是 SSH 登录的主流方式,公钥未上传、格式错误、权限不对均会导致 “Permission denied (publickey)”。
场景 1:客户端公钥未上传到服务器
错误现象
- 客户端日志:Permission denied (publickey);
- 服务器日志:No more authentication methods to try. ops from 192.168.1.10 port 54321 ssh2。
排查步骤
- 确认客户端公钥文件存在(默认 ~/.ssh/id_rsa.pub 或自定义密钥的 .pub 文件):
|
# 客户端执行:查看公钥文件 ls -l ~/.ssh/id_rsa.pub # 若提示 No such file or directory,说明未生成密钥 |
- 确认服务器端 authorized_keys 中是否有客户端公钥:
|
# 若能通过密码登录服务器(临时允许),执行: ssh -o PasswordAuthentication=yes ops@10.0.1.10 "cat ~/.ssh/authorized_keys" # 对比客户端公钥(输出是否包含客户端 ~/.ssh/id_rsa.pub 的内容) cat ~/.ssh/id_rsa.pub |
解决方案
- 客户端生成密钥(若未生成):
|
ssh-keygen -t ed25519 -C "ops@client" # 生成 ed25519 密钥(比 RSA 更安全) # 按回车默认保存到 ~/.ssh/id_ed25519,可选设置密码(passphrase) |
- 上传客户端公钥到服务器:
|
# 方法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 权限 / 属主错误
错误现象
- 客户端日志:Permission denied (publickey);
- 服务器日志:Bad owner or permissions on /home/ops/.ssh/authorized_keys。
排查步骤
- 登录服务器(临时密码登录),查看 authorized_keys 及其父目录 .ssh 的权限和属主:
|
# 查看 .ssh 目录权限(应是 700,属主为登录用户) ls -ld ~/.ssh # 查看 authorized_keys 权限(应是 600,属主为登录用户) ls -l ~/.ssh/authorized_keys |
- 常见错误权限:
- .ssh 目录权限为 755(其他用户可进入);
- authorized_keys 权限为 644(其他用户可读);
- 属主为 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:客户端密钥权限过宽
错误现象
- 客户端日志:Permissions 0644 for '/home/ops/.ssh/id_ed25519' are too open;
- 后续提示:Permission denied (publickey)。
排查步骤
- 客户端查看密钥文件权限:
|
ls -l ~/.ssh/id_ed25519 # 若输出 -rw-r--r--(644),则权限过宽 |
- 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:公钥格式错误或不完整
错误现象
- 客户端日志:Permission denied (publickey);
- 服务器日志:Invalid key data in /home/ops/.ssh/authorized_keys: 1(第 1 行公钥无效)。
排查步骤
- 客户端查看公钥格式(以 ed25519 为例,应是一行完整字符串):
|
cat ~/.ssh/id_ed25519.pub # 正确格式:ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIL... ops@client |
- 常见格式错误:
- 公钥被换行拆分(多行);
- 末尾注释包含特殊字符(如中文、空格);
- 复制时遗漏开头 ssh-ed25519 或末尾注释。
解决方案
- 客户端重新复制完整公钥:
|
# 用 cat 输出并复制,避免手动换行 cat ~/.ssh/id_ed25519.pub |
- 服务器端替换错误公钥:
|
# 登录服务器,编辑 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)
错误现象
- 客户端日志:Permission denied (publickey);
- 若客户端尝试密码登录,提示:No supported authentication methods available。
排查步骤
- 查看服务器端 sshd_config 中 PasswordAuthentication 配置:
|
# 登录服务器(若能通过密钥登录),执行: sudo grep -i "PasswordAuthentication" /etc/ssh/sshd_config # 若输出 PasswordAuthentication no,说明禁用密码登录 |
- 错误场景:客户端未上传公钥,却尝试用密码登录,服务器仅允许密钥认证,导致拒绝。
解决方案
根据需求二选一:
- 方案 1:启用密码登录(临时调试):
|
sudo vim /etc/ssh/sshd_config # 修改为: PasswordAuthentication yes # 测试配置语法并重启服务 sudo sshd -t sudo systemctl restart sshd # 此时可通过密码登录,再上传公钥 |
- 方案 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)
错误现象
- 客户端日志:Permission denied, please try again.;
- 服务器日志:User root from 192.168.1.10 not allowed because PermitRootLogin is set to no。
排查步骤
- 确认客户端登录用户是 root:
|
# 客户端登录命令(若包含 root@) ssh root@10.0.1.10 # 此时服务器禁止 root 登录 |
- 查看服务器端 PermitRootLogin 配置:
|
sudo grep -i "PermitRootLogin" /etc/ssh/sshd_config # 若输出 PermitRootLogin no,说明禁止 root 直接登录 |
解决方案
根据安全需求选择:
- 方案 1:用普通用户登录后提权(推荐,安全):
|
# 客户端用普通用户 ops 登录 ssh ops@10.0.1.10 # 登录后用 sudo 提权(需 ops 在 sudoers 中) sudo -i # 切换到 root |
- 方案 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)
错误现象
- 客户端日志:Permission denied, please try again.;
- 服务器日志:User test from 192.168.1.10 not allowed because not listed in AllowUsers。
排查步骤
- 查看服务器端 AllowUsers 或 AllowGroups 配置:
|
sudo grep -i "AllowUsers" /etc/ssh/sshd_config sudo grep -i "AllowGroups" /etc/ssh/sshd_config |
- 常见限制:
- AllowUsers ops admin:仅允许 ops 和 admin 登录,test 用户不在列表;
- AllowGroups ssh-users:仅允许 ssh-users 组用户登录,test 不在该组。
解决方案
- 方案 1:将用户加入 AllowUsers:
|
sudo vim /etc/ssh/sshd_config # 修改为(添加 test 用户): AllowUsers ops admin test # 重启服务 sudo systemctl restart sshd |
- 方案 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 语法错误
错误现象
- 客户端登录提示:Connection closed by 10.0.1.10 port 2222;
- 服务器端重启 sshd 失败:Job for sshd.service failed;
- 间接导致登录时无认证方式可选,提示 Permission denied。
排查步骤
- 测试 sshd_config 语法(核心!语法错误会导致 sshd 加载配置失败):
|
sudo sshd -t # 若有错误,会提示具体行号,如: # /etc/ssh/sshd_config line 56: Bad option: PasswordAuthentiation |
- 常见语法错误:
- 参数拼写错误(如 PasswordAuthentiation 少写一个 c);
- 参数值错误(如 PermitRootLogin 0,应为 yes/no);
- 多余符号(如行尾多一个分号 ;)。
解决方案
- 根据 sshd -t 提示修改错误行:
|
# 编辑 sshd_config,定位错误行(如 line 56) sudo vim +56 /etc/ssh/sshd_config # 修正拼写错误,如 PasswordAuthentiation → PasswordAuthentication |
- 测试语法无误后重启服务:
|
sudo sshd -t # 无输出则语法正确 sudo systemctl restart sshd |
验证
|
# 客户端重新登录,若能正常进入认证阶段,说明解决 ssh -v ops@10.0.1.10 |
场景 9:客户端 ~/.ssh/config 权限过宽
错误现象
- 客户端登录提示:Bad owner or permissions on /home/ops/.ssh/config;
- 后续无法加载配置,默认用密码登录,若服务器禁用密码,则提示 Permission denied。
排查步骤
- 客户端查看 config 文件权限:
|
ls -l ~/.ssh/config # 若输出 -rw-r--r--(644)或 -rwxr-xr-x(755),则权限过宽 |
- 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 配置冲突(密钥路径错误)
错误现象
- 客户端日志:Permission denied (publickey);
- 调试日志显示:Offering public key: /home/ops/.ssh/id_rsa(实际密钥是 id_ed25519)。
排查步骤
- 查看客户端 config 中 IdentityFile 配置:
|
grep -i "IdentityFile" ~/.ssh/config # 若输出 IdentityFile ~/.ssh/id_rsa,而实际密钥是 id_ed25519,则路径错误 |
- 配置冲突导致客户端提供错误的密钥,服务器拒绝,出现 Permission denied。
解决方案
- 修改 config 中的 IdentityFile 为正确路径:
|
vim ~/.ssh/config # 修改为: IdentityFile ~/.ssh/id_ed25519 |
- 若用别名登录,确保别名配置正确:
|
# 示例: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 个核心原则
- 先看日志,再动手:客户端 ssh -v 和服务器端日志是定位问题的 “钥匙”,不要盲目尝试登录;
- 先查权限,再查配置:80% 的 “Permission denied” 与权限相关(密钥、.ssh、authorized_keys),优先排查;
- 修改前备份,修改后测试:修改 sshd_config 前备份(cp /etc/ssh/sshd_config{,.bak}),用 sshd -t 测试语法,避免改坏后连不上。
按照本文的步骤,你可在 5-10 分钟内定位并解决绝大多数 “Permission denied” 问题,从 “登录失败” 快速过渡到 “连接成功”。若遇到特殊场景(如 LDAP 认证、双因素认证),可结合对应日志进一步排查,或在评论区留言补充!
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐



所有评论(0)