☰
SSH与VNC登录报错排查指南:从Permission denied到Caps Lock
2026/10/18 6:24:32 网站建设 项目流程

SSH 登录报错Permission denied和 VNC 登录报错Hint: Caps Lock on,这俩提示我估计做过服务器运维或者远程桌面支持的人都见过,而且十有八九都经历过同一件事:看到报错的第一反应是“密码输错了”,然后反复重试,最后发现根本不是那回事。这两个报错藏着的坑比表面上看起来多得多,尤其是当你同时在维护几台服务器、记着好几套密码的时候,它们会把你的排查思路带进死胡同。这篇文章我不打算讲什么高深理论,就围绕这两个报错,把我这些年实测过的排查链路、真正的原因分布、以及那些文档里不会写的细节,全部拆开揉碎讲一遍。

先说清楚适合什么人看:刚接触 Linux 服务器的新手、需要给同事远程做技术支持的人、自己搭过 VNC 但又时不时登不上的朋友。如果你已经熟到扫一眼日志就知道问题所在,这篇里的部分内容对你可能偏基础,但第三节和第四节里的配置细节、权限要求,包括日志关键行的解读方式,还是值得快速过一遍。

1. Permission denied 不等于密码错误:先分清五种常见假象

很多人看到Permission denied, please try again就默认是密码不对,其实这是最大的误判。SSH 的密码认证失败会报这个,但密钥认证失败、用户不存在、账户被锁、甚至客户端本地的键盘映射出问题,最终被服务端拒绝时,呈现给你的几乎都是同一句话。我统计过自己踩过的坑,真正是“单纯密码记错”的情况其实只占一小部分,多数时候是下面几种假象在干扰判断。

1.1 用户名就写错了,但客户端不会告诉你

SSH 登录时你输入的是用户名@地址,如果用户名本身不存在或者写错,服务端在默认配置下不会直接说“这个用户不存在”,而是同样返回Permission denied。这么做的目的是防止攻击者通过报错猜测有效用户名。很多人这时候会死磕密码,把大小写、特殊字符试了个遍,其实应该先确认用户名本身。

你可以用ssh -v user@host看客户端的输出,它会明确告诉你正在尝试的用户名是什么。另外一个我常用的办法是换一个自己确定存在的用户登录试试,如果换用户之后能进,那问题十有八九出在用户名上,而不是密码。

1.2 键盘布局和密码里的特殊字符

这个坑隐蔽得很。远程服务器密码里如果包含@、#、~、^这类字符,而你的本地键盘布局是中文输入法状态,或者笔记本没有开启数字小键盘切换,打出来的字符和你想的完全不是同一个。比如中文输入法下按@可能直接没反应,或者输入了全角字符,服务端收到的密码自然不对。

更坑的是,VNC 那类图形化登录界面里密码框是密文的,你压根看不到自己输了个啥。SSH 终端虽然也是密文,但起码可以在本地先开个文本编辑器,切到英文布局,把密码敲进去看一眼再复制粘贴。记住一个原则:涉及密码的操作,先把输入法切到英文、把大写锁定关掉再动手。

1.3 密钥优先,密码被忽略

如果你的~/.ssh目录里配置了密钥,SSH 客户端默认会优先尝试公钥认证。这时候就算密码是对的,只要密钥认证失败或者服务端不接受该密钥,客户端也不会回头用密码去试(至少 OpenSSH 默认行为是这样,除非你在命令行加了-o PreferredAuthentications=password)。于是你看到的现象就是:密码明明没错,但一直Permission denied。

我遇到过一次最离谱的情况:某台服务器上,我发现.ssh目录里不知道什么时候多了一个权限是 777 的id_rsa,客户端加载私钥的时候直接拒绝使用“权限过于开放”的密钥,结果卡在密钥认证环节反复失败。删掉那个密钥文件、改用密码登录就好了。所以,遇到 Permission denied,先确认是不是有密钥在“捣乱”,用ssh -v看认证过程到底走的是哪条路。

1.4 账户锁定和 PAM 策略

服务端的 PAM 配置如果开启了账户锁定模块(比如pam_faillock),连续输错几次密码之后,账户会被临时锁定。这时候你拿到正确密码也登不进去,依然显示Permission denied。属于“密码没错,但被锁了”。

服务端日志里会明确看到Account locked due to N failed logins之类的记录,而客户端这边除了Permission denied什么都看不出来。这个假象最有迷惑性,因为你压根不知道账户被锁,只会觉得“难道我又记错密码了”。

1.5 防火墙或 Fail2ban 在背后拦截

还有一种情况更隐蔽:客户端连上了,TCP 握手也完成了,但还没到密码认证这一步就被服务端的 Fail2ban 丢进黑洞。表现为 SSH 端口能通、输入用户名之后要等很久才返回Permission denied,或者干脆直接断连。这其实是服务端把某个 IP 列入黑名单导致的,换一台机器或者换个网络就能避开,但只要你的 IP 还在黑名单里,密码再对也没用。

这个假象最好用ssh -vvv识别——如果你发现程序卡在banner exchange阶段很长时间,之后才报错,多半是在防火墙或 Fail2ban 层面被卡住了,而不是密码本身的锅。

2. 真正的破案现场:SSH 服务端日志与客户端详细模式

排查 SSH 登录问题,别在客户端反复试密码,那是浪费生命。真正告诉你“为什么被拒”的,是服务端的日志。我通常的做法是:一边在客户端用ssh -vvv重试,一边在服务端盯日志,两边对照,半小时以内基本都能定位。

2.1 服务端日志去哪里看

Debian 系的系统看/var/log/auth.log,Red Hat 系看/var/log/secure,用 systemd 的发行版还可以直接journalctl -u sshd(或者journalctl -u ssh,具体看你的服务名)。日志里会出现这几类关键行:

日志关键内容含义对应解决方案
Failed password for invalid user xxx用户名不存在或写错核实用户名
Failed password for xxx from IP密码真的不对重置密码或检查键盘布局
User xxx not allowed because account is locked账户被锁定passwd -u解锁
Connection closed by authenticating user xxx密钥认证过程中直接断连检查公钥格式、authorized_keys 权限
Unable to negotiate with IP port xxx: no matching host key type客户端与服务端密钥算法不匹配在服务器配置中开放相应算法或更新客户端

我建议你把journalctl -u sshd -f挂在一个终端窗口里,然后去客户端重试一次登录,观察日志实时输出的那几行。这一招能瞬间帮你把问题从“猜”变成“看”,比你在客户端瞎琢磨高效十倍。

2.2 客户端ssh -vvv的关键行解读

-v级别已经能看到认证过程的大致走向,-vvv几乎把每一步都摆出来了。我在排查时最关注这几行:

  • debug1: Next authentication method: publickey—— 说明现在正在尝试公钥认证。
  • debug1: Offering public key: ...—— 客户端把本地某个公钥发给服务端了,但这里不代表成功,只是“试探”。
  • debug1: Authentications that can continue: publickey,password—— 服务端说你还可以继续用公钥或密码,说明公钥尝试被拒了。
  • Permission denied (publickey,password).—— 所有可用认证方式都试过且失败了。

有一个容易忽略的细节:如果客户端输出的最后一行只有publickey而没有password,说明服务端根本没开放密码登录。你输多少次密码都没用,得先改服务端配置或者改用密钥。

2.3 判断问题归属:用户问题还是配置问题

知道怎么在两端收集信息之后,判断归属就变得简单了:服务端日志显示“密码错误”,那就是用户侧问题(密码、键盘、记错);日志显示“invalid user”,那是用户名问题;日志显示“Connection closed”且客户端报错在认证协商阶段,那是配置或网络中间设备问题。只要你能看到日志,就不要再反复试密码,先读日志,读懂了再动手。盲目重试不仅浪费时间,还可能触发账户锁定策略,给自己挖更大的坑。

3. 授权文件与配置文件的隐蔽雷区:authorized_keys 权限和 sshd_config 细节

排除了上面那些用户层面的假象之后,如果依然Permission denied,那问题大概率落在服务端的授权文件和配置上。这里面的坑比看上去多得多,而且很多是“改一次就坏、坏一次就很久查不出来”的类型。

3.1 权限要求不是玄学,是安全底线

.ssh目录权限必须是700,authorized_keys文件权限必须是600,这俩是硬性要求。OpenSSH 对权限过于宽松的密钥文件会直接拒绝使用,原因很简单——如果其他用户能读你的私钥或改你的授权文件,那密钥认证就失去了意义。

我身边一位同事就踩过这个坑:他想给authorized_keys加一个新公钥,为了方便直接chmod 777 authorized_keys,改完发现所有密钥登录全部失效,而且报错就是笼统的Permission denied。他在客户端折腾了两个小时,最后我用ssh -vvv看到Authentication refused: bad ownership or modes,一看权限,秒破。改完权限之后,用ls -ld ~/.ssh && ls -l ~/.ssh/authorized_keys确认一下,别假装自己记住了。

如果是通过 root 帮普通用户添加公钥,还要注意文件属主是不是对应用户,比如把 root 生成的authorized_keys直接复制给某个用户,属主是 root,用户登录一样会被拒。这是权限问题里最容易被忽略的一环。

3.2 sshd_config 里的隐形开关

/etc/ssh/sshd_config中这几个参数基本决定了登录成败:

  • PasswordAuthentication yes—— 是否允许密码登录,如果为 no,密码正确也没用。
  • PubkeyAuthentication yes—— 是否允许公钥登录,如果为 no,密钥配得再好也没用。
  • PermitRootLogin prohibit-password—— 字面意思是禁止 root 用密码登录,但不同版本默认值不同,有时候你以为开了密码登录,其实 root 就是被排除在外的。
  • AllowUsers/AllowGroups—— 白名单机制,只要不在这列表里的用户一律拒绝,而且提示也是 Permission denied。

我在某个项目里搭过一批测试服务器,复制配置的时候不小心把AllowUsers写成了AllowUser,配置文件里的旧参数被覆盖,所有用户全部无法登录。服务端日志里能看到User xxx not allowed because not listed in AllowUsers,但客户端显示还是一样的Permission denied。改完sshd_config之后,至少用sshd -t做一次语法检查,同时保持当前的 SSH 连接不退出,避免把自己锁在外面。

3.3 密钥类型和注释符的坑

有公钥加进去了却依然登不上,还有一种情况是公钥格式写错了。authorized_keys文件里每行只能有一条公钥,以ssh-rsa、ssh-ed25519等开头。如果你复制的时候不小心把ssh-rsa AAA...里的ssh-rsa丢了三两个字符,或者把注释里的#放在了不该放的位置,整条密钥可能直接失效。另外,老版本 OpenSSH 不认新版的ssh-ed25519格式,新版本对ssh-rsa的默认策略也变了,导致某些旧密钥连接时报no matching host key type。这种情况在客户端-vvv的输出里会出现no mutual signature algorithm这类明确提示,根源是服务端和客户端各自只支持不同算法,需要手动在服务端启用对应算法,或者升级客户端。

4. VNC 的 “Caps Lock on” 提示:表象与真实原因

VNC 登录报错里弹出一个Hint: Caps Lock on,这个提示的设计初衷是好的——它想告诉你说,当前密码框检测到大写锁定是开着的,如果你密码里包含小写字母,可能会因此输错。但实际使用中,这个提示经常有误导性,你明明关掉了大写锁定,它还是会弹出来。那说明什么?说明问题根本不在 Caps Lock 上。

4.1 为什么 VNC 会专门提示 Caps Lock

VNC 的密码认证机制特殊在它是自己的独立密码体系。常见的 VNC 服务(比如 TigerVNC、x11vnc、TightVNC)默认使用独立的密码文件,这个密码是安装时用vncpasswd生成或设置的,和系统用户的登录密码是两套东西。因此,VNC 登录界面无法像 SSH 那样做服务端账户认证,它只能靠密码本身对不对来判。如果你输入的密码和密码文件里保存的不一致,VNC 服务为了“引导”用户,会在返回错误时附带一个提示:检查大写锁定。这本来是对“用户输错密码”的一种猜测性提示,但很多人直接根据提示去检查 Caps Lock,结果发现没问题,然后又陷入死循环。

4.2 密码大小写确认之后,密码对不上的真实原因

我遇到过的 VNC 登录失败,根因分布大概是这样:

  • 把 SSH 密码、系统登录密码当成了 VNC 密码——这是最常见的坑。VNC 密码是独立设置的,跟系统密码完全可以不一样。
  • vncpasswd设置时没有回显,输错了自己不知道。VNC 密码输入框是密文的,设置时你看着像在打空气,很容易在设置阶段就把错误密码存了进去。当时设的时候没注意大小写,后面登录自然怎么输都不对。
  • 密码文件权限不对:~/.vnc/passwd文件权限如果不是600,部分 VNC 服务出于安全考虑会拒绝读取或认作无效。这就表现为密码明明没变但突然登录失败。
  • VNC 密码的长度限制:很多 VNC 实现只取密码的前 8 位,超过 8 位的部分会被悄悄截断。你设置了一个 10 位的密码,登录时输入 10 位,如果输入法或键盘映射让前八位中某一位出错,服务端拿到的密码就废了。
  • 密码过期或账户锁定:在 x11vnc 开启了 PAM 认证的前提下,VNC 其实是在调系统账户认证,这时候如果系统用户密码过期、账户被锁,VNC 登录也会失败,但提示同样可能包含Caps Lock on。

4.3 键盘映射差异:Windows 客户端和 macOS 客户端的不同表现

VNC 客户端在不同操作系统上的键盘映射处理并不统一。Windows 下的某些 VNC Viewer 对大小写锁定的处理方式跟服务端不一致,可能你本地看到 Caps Lock 是关的,但服务端收到的按键流仍然是“大写锁定生效”的状态。更诡异的是某些客户端在密码输入框里会自动忽略你的 Caps Lock 状态,直接把按键映射成大写字母。

处理方法是先在本地任意文本编辑器里输入一遍密码,确认大小写和实际内容,然后再复制到 VNC 客户端,尽量让客户端以“粘贴”方式而不是“击键”方式输入密码。另外,如果客户端有“自动锁定大小写”这类选项,先关掉再试。

4.4 Silently authenticate: 日志才是唯一的裁判

和 SSH 一样,VNC 服务端也会记录认证尝试的结果。TigerVNC 的日志在~/.vnc/*.log里,x11vnc 可以用-o参数指定日志文件。如果日志里明确写了Authentication failed,那问题就是在密码本身;如果日志里没有认证失败记录,只是连接被断开,那就要去看防火墙、显示编号端口(默认 5900 起)是否可达。被提示误导的时候,先把日志找出来看一眼,比按提示狂切大小写有效得多。

5. 一张表理清排查顺序:从快速判断到根因定位

说了这么多,最后给一份可以直接照着走的排查清单。不用记那么多理论,按这个顺序操作,绝大多数问题都能在十分钟内定位。

5.1 SSH 侧快速排查表

步骤操作判断依据对应处理
1确认用户名正确服务端日志是否显示invalid user修正用户名
2本机输入法切英文,确认密码无误换已知密码的用户在小范围试一次重置密码或用已知账户验证
3ssh -v观察认证方法看是走了 publickey 还是 password按需加-o PreferredAuthentications=password
4查看服务端日志Failed password、not allowed、locked等关键词按关键词修正
5检查authorized_keys和.ssh权限bad ownership or modeschmod 700 ~/.ssh && chmod 600 ~/.ssh/authorized_keys
6检查sshd_config里的白名单与认证开关AllowUsers、PasswordAuthentication修改后sshd -t并重载

5.2 VNC 侧快速排查表

步骤操作判断依据对应处理
1确认 Caps Lock 状态并关闭本地编辑器里输入密码检查大小写关闭 Caps Lock 后重试
2确认用的是 VNC 独立密码,不是系统密码你是否设置过vncpasswd用vncpasswd重新设置独立密码
3确认密码文件权限ls -l ~/.vnc/passwd修改为600
4检查密码长度VNC 密码是否超过 8 位缩短到 8 位以内再试
5看 VNC 服务端日志是否有Authentication failed根据日志类型处理
6确认端口和防火墙5900/5901 等端口是否可达放行端口或检查显示编号

5.3 组合场景下的快速判断

有时候 SSH 能登,VNC 不能登,或者反过来。这里说几个我实际遇到的组合:

  • SSH 能登、VNC 不能登:几乎可以排除系统账户本身的问题,重点查 VNC 独立密码、密码文件权限、VNC 服务进程是否在监听对应端口。
  • SSH 不能登、VNC 能登:说明系统账户和密码没问题,问题很可能出在 SSH 密钥、服务端sshd_config的认证开关、AllowUsers白名单上。
  • 两个都登不上:优先怀疑系统账户锁定或密码过期,先到服务端本地用passwd或图形界面确认账户状态,再回头处理远程工具。
  • 换网络后 SSH 能登、原网络不能登:大概率是 IP 被防火墙或 Fail2ban 封禁,别改密码,先解封。

6. 我自己的处理习惯与一个冷门小技巧

最后分享一点个人经验。我平时排查这类问题,绝不会在同一个终端里重复尝试超过三次。第一次失败,我会去服务端打开日志;第二次失败,我会对照ssh -vvv输出和服务端日志;第三次失败还查不出来,我就放弃“猜”,直接用 tcpdump 在服务端抓包看认证过程的交互顺序——虽然这个手段对新手来说有点重,但对判断“密钥协商到哪一步才断的”极其有效。

再送一个冷门但很实用的小技巧:如果是自己临时用的服务器,密码中包含大小写字母,可以先在登录信息里故意写成小写,引发一次登录失败,再观察服务端日志里的Failed password for xxx from IP这一行。日志里你录入的密码是明文回显的(在 auth.log 里是Failed password for test from 192.168.x.x port 22 ssh2,不显示密码内容,但在某些配置下会显示用户名),虽然看不到密码本身,但能看到服务端是否认为这个用户存在、是否因某种策略拒绝。对于判断是“用户不存在”还是“密码错误”,这一步零成本且极快。

说实话,这两个报错单独看都是入门级别的问题,但把它们叠加在真实的服务器环境里,背后隐藏的用户锁定、权限问题、密钥优先级、独立密码机制,任何一个环节出错都会让排查变得异常痛苦。把这些链条理顺之后,你会发现大多数“登录失败”问题根本轮不到重装、轮不到重置系统,往往只是一个小配置、一个权限、一个客户端输入状态的问题。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询