你打开FinalShell,填入ubuntu服务器的IP,用户名root,密码敲了一遍又一遍,回车之后还是弹窗:“密码错误”。你甚至把密码复制粘贴进去,确保每一个字符都没错,依然进不去。这种体验我太熟悉了,因为FinalShell连接ubuntu提示密码这个事,看起来是个“密码问题”,实际上绝大多数时候跟密码本身一点关系都没有。本文就围绕这个精确场景,把服务端配置、客户端行为、认证链路、排查顺序一次性讲透。
先给大家一个结论:SSH连接ubuntu一直提示密码,排除了真正的密码输错之外,剩下的原因高度集中在ssh服务端配置、用户状态、客户端密钥机制这三个层面。下面逐一拆解。
1. 先分清“密码错误”和“认证被拒”:八成的问题都出在判断偏差上
遇到“一直提示密码”,第一步不是反复输密码,而是先判读连接失败的具体表现。SSH连接失败其实有完全不同的几种反馈,很多人没区分,导致排查方向一开始就错了。
1.1 连接失败的三种反馈形式
第一种是“Connection refused”或者“Connection timed out”,这种情况压根没走到认证环节,是网络不通或者ssh服务没起来,和密码毫无关系。
第二种是提示“Permission denied, please try again.”,这是真正走到了密码校验环节,服务端明确拒绝了。但也分两种情况:密码确实不对,或者密码其实是对的,但服务端不允许你这个用户名用密码登录。
第三种是更特殊的,就是你输一次密码,它弹一次窗口,明明提示成功或者没报错,然后又弹一次,像鬼打墙一样。这种往往是FinalShell的认证方式选择和服务器接受的认证方式没对齐,后面专门讲。
很多人只看到“提示密码”三个字,就默认是自己密码记错了,尤其是刚重装过系统、刚买VPS、刚创建虚拟机的场景,自己都怀疑是不是真的把密码设错了。但其实,ubuntu系统里“密码正确但无法SSH登录”的情况非常普遍,比重远高于你的想象。
1.2 理解SSH认证顺序才能定位问题
SSH登录时,服务端并不是只问“密码对不对”这一个问题。它会先检查客户端提供的认证方法,然后按照预定的顺序尝试:公钥认证(publickey)、密码认证(password)、键盘交互(keyboard-interactive)等。
如果服务端配置了PasswordAuthentication no,那么无论你密码输得多么准确,服务端都会拒绝密码认证,表现就是反复提示密码,或者直接告诉你认证失败。如果你还打开了/etc/ssh/sshd_config.d/下的某个覆盖文件,那就算主配置文件里写的是yes,也可能被改成no。
这里需要明确一个关键认知:用户看到的“密码错误”提示,在SSH协议层面实际是“认证失败”的统称,它可能是密码错、用户不存在、认证方法被禁用、用户被锁定等多种原因。所以不要跟密码死磕,要从认证链路往上查。
2. 服务端才是主战场:sshd配置、用户状态和ubuntu特有问题
排查方向确认后,把目光转向ubuntu服务器本身。这一节是整个排障过程里的核心,因为绝大多数“一直提示密码”的根源都在这里。
2.1 ubuntu系统里sshd服务甚至可能根本不存在
这是个非常反直觉但极其常见的问题:市面上很多ubuntu云镜像、WSL、虚拟机的模板,默认是不安装openssh-server的。你在FinalShell里填IP、用户名、密码,如果端口22没有监听,客户端会秒级收到“Connection refused”。
但如果你用的是某些定制镜像,防火墙把22端口丢弃了,表现又不一样,会一直卡在连接中,然后超时。这里可以先用一行命令确认服务端到底有没有装、有没有在跑:
sudo systemctl status ssh如果提示Unit ssh.service could not be found.,那基本就真相大白了。装一个就行:
sudo apt update sudo apt install openssh-server -y sudo systemctl enable --now ssh很多教程里会直接让你去改sshd_config,但如果连服务都没装,改配置自然毫无意义。我见过不少新手在没装sshd的服务器上配置了半天,怎么输密码都被拒,最后发现是空跑。
2.2 sshd_config里三个核心开关决定你能否登录
当ssh服务确认在运行之后,就需要检查配置。ubuntu的SSH主配置文件在/etc/ssh/sshd_config,但重点提醒,ubuntu从20.04之后,系统强烈推荐在/etc/ssh/sshd_config.d/目录下放覆盖文件。这个目录里的.conf文件优先级更高,无语的是很多教程都只讲主配置,导致一些人改了主文件根本没生效。
需要确认的核心参数有三个。第一个是PasswordAuthentication,必须为yes。第二个是PubkeyAuthentication,如果某些场景下你的客户端可能被引导使用密钥认证,这个值建议是yes,如果是no也会导致公钥认证路径异常。第三个是PermitRootLogin,如果你要用root登录,这个值必须是yes或者prohibit-password(禁止密码、但允许密钥),很多ubuntu默认是prohibit-password,相当于你拿密码登录root一定是失败的。
检查命令可以这样组合:
sudo sshd -T | grep -E 'passwordauthentication|pubkeyauthentication|permitrootlogin'注意,sshd -T输出的是实际生效的配置,它会把主文件和覆盖文件合并后的结果展示给你,比直接grep sshd_config靠谱得多。如果你看到passwordauthentication no,那就要去找到底是谁把这个值改掉了:
grep -r "PasswordAuthentication" /etc/ssh/sshd_config /etc/ssh/sshd_config.d/如果是某个.conf文件设置成了no,把它改成yes之后重启ssh服务即可。
2.3 用户状态被忽略的坑:root禁用、密码过期、空密码策略
服务端配置正常之后,还得看用户本身。
第一个是root用户。ubuntu默认安装时,root是没有密码的,普通用户通过sudo提权。如果要用ssh root@ip,必须提前给root设置密码:sudo passwd root,同时保证PermitRootLogin不是no。否则你密码输一万遍也没用,因为god用户本身就没有可用的密码登录态。
第二个是用户的密码过期。公司电脑或某些定制镜像可能会设置密码有效期,密码过期之后SSH登录会被强制要求修改密码,但TTY模式下FinalShell的处理方式又是弹窗让你输新密码,这个弹窗逻辑会让人觉得“一直在要密码”。可以临时用其他方式登录服务器执行chage -l 用户名查看状态,如果过期了就用sudo chage -M 99999 用户名改掉。
第三个是空密码问题。有些人在创建用户时没有设密码,ubuntu的sshd默认配置里有PermitEmptyPasswords no这一条,空密码用户直接拒绝登录。反正别指望不设密码能连上。
2.4 改完配置必须重启服务并验证语法
SSH配置修改完之后,直接sudo systemctl restart ssh之前,建议先跑一遍sudo sshd -t,这个命令会检查配置语法是否有问题。如果配置写错了,重启之后sshd直接退出,反而更麻烦。
sudo sshd -t sudo systemctl restart ssh sudo systemctl status ssh很多人的实际场景是改完配置之后忘了重启,或者重启的是sshd而不是ssh服务名,导致改了等于没改。在ubuntu上,systemctl restart ssh和systemctl restart sshd都能用,因为ssh.service和sshd.service是同一个单元的别名,但保险起见还是用ssh。
服务端的问题排查到这里,覆盖了至少七成的案例。接下来看客户端侧,也就是FinalShell本身的机制。
3. FinalShell客户端侧的隐性干扰:密钥优先、缓存和弹窗逻辑
FinalShell是一个来自国内开发者的SSH工具,集成了终端、文件管理、流量监控等一堆功能,很多人在Windows环境下首选它连ubuntu。但它对SSH认证过程的处理逻辑,跟OpenSSH命令行客户端并不完全一样,某些默认行为恰恰会造成“密码一直弹窗”的假象。
3.1 第一次新建连接时的认证方式选择陷阱
新建FinalShell会话时,右侧会有一个认证方式的选择,常见是“密码”和“密钥”。如果你选了密钥,但密钥文件没有配置或者路径指向错误,FinalShell每次发起连接时都会先尝试密钥认证,失败后回落到密码认证。这个回落过程理论上是自动的,但FinalShell某些版本在密钥文件缺失时会直接弹出密码框,而且这个密码框跟普通密码框长得一样,看起来就是“一直提示密码”。
还有一种情况是,你明明输的是密码,但FinalShell内部优先把输入框当成密钥口令(passphrase),如果密钥文件的密码和用户密码不一致,它会一直提示错误。这种错位非常隐蔽。
排查方法很简单:在会话配置里,把认证方式明确改成“密码”,不要留空也不要选密钥。然后重新连接试试。
3.2 公钥认证优先引发的“鬼打墙”
如果服务器端同时授权了公钥和密码登录,而FinalShell的会话配置里自动加载了本机已有的密钥文件(比如C:\Users\你的用户名\.ssh\id_rsa),那么连接时会先走publickey认证。如果这个密钥没有被服务器认可,OpenSSH服务端会告诉你“继续尝试其他方法”,FinalShell就会弹出密码输入框。
如果这个弹窗逻辑出现bug,在公钥认证反复失败的情况下,它就陷入密码框弹完又一个密码框的循环。这种问题在局域网连接虚拟机时特别常见,因为很多人给FinalShell配过密钥,后来虚拟机重装系统了,但FinalShell那边的密钥没删。
处理方法:在FinalShell的“会话属性 -> 认证”里把私钥文件选项清空,或者在全局设置里把“优先使用公钥认证”的勾选去掉。之后再连,它就会老老实实走密码认证。
3.3 已保存的密码和远端主机KEY不匹配
SSH有一个机制叫主机密钥校验(host key checking)。第一次连接新IP时,OpenSSH会显示主机指纹让你确认。FinalShell作为图形客户端,通常忽略了这一步,但在后台它会保存一份“此IP对应主机密钥”的缓存。
如果服务器重装过系统,或者换了不同的系统镜像,它的主机密钥变了,但FinalShell缓存里还是旧的。某些版本的FinalShell不会直接报“host key mismatch”,而是反复弹密码框,导致你误以为密码错了。这个问题在虚拟机调试场景下极其典型——“我昨天还能连,今天重装ubuntu再连就连不上了”。
这种问题有两个解法:第一个是删除缓存,FinalShell的连接缓存一般在安装目录或者用户目录下,不同版本位置不同,你可以打开FinalShell的安装目录找类似known_hosts的文件删掉;第二个是在会话属性里找到“校验服务器公钥”之类的选项,把它关掉,适合自己搭的实验室环境,但云服务器生产环境不建议关。
3.4 用OpenSSH命令交叉验证是拆穿假象的最快手段
如果你不确定问题在服务端还是客户端,可以直接在Windows命令行里跑一次OpenSSH客户端(Win10/11自带):
ssh -vvv 用户名@IP-vvv会把认证过程从头到尾打印出来。如果它显示Permission denied (publickey,password),说明服务器端在用密码之前拒绝了认证,基本就是服务端配置问题。如果它正常提示输入密码且输入正确后秒连,那你就知道问题出在FinalShell自身的配置或版本上,直接卸载换最新版或者重置配置就行。
这个交叉验证法,是区分“服务器拒绝”和“客户端抽风”最直接的方法。很多被FinalShell折腾半天的人,用命令行一试就清楚了。如果命令行也提示密码错,再回到服务端查看日志:
sudo tail -f /var/log/auth.log连接一次看一次日志。如果末尾出现Failed password for root from 192.168.x.x port xxxx ssh2,说明密码确实不对或者密码认证被拒,日志里通常会附带具体用户名,信息量很大。
4. 从零开始的一张排障路线图:虚拟机、云服务器和局域网都适用
前面把原理讲清楚了,这一节给出一个可以直接照着操作的完整排查链路。这个链路我自己每次帮人远程排查SSH问题时都照着走,基本能在五分钟内定位问题。
4.1 第一步:确认网络层通不通
网络层能做两件事:ping和telnet。ping不通不代表SSH连不上,因为有些网络环境禁ICMP;ping通了也未必没问题,因为防火墙可能只禁了22端口。
ping 服务器IP telnet 服务器IP 22telnet通的话,窗口会显示类似SSH-2.0-OpenSSH_8.9p1 Ubuntu-3ubuntu0.4这样的版本文本。这意味着ssh服务已经在监听,网络层面没问题。如果telnet提示Connection refused,服务没起或者端口不对;如果卡住不动,防火墙丢弃了包。
如果服务器在虚拟机里,还要确认虚拟机网络模式是NAT还是桥接。NAT模式下宿主机能连虚拟机但外部设备和FinalShell不一定能直连,很多人在VMware里装好ubuntu,宿主机FinalShell连不上,原因就是NAT模式和IP网段配置的问题,跟密码一点关系都没有。这种场景我建议直接用桥接模式或者使用NAT端口转发,否则密码再对也上不去。
4.2 第二步:确认服务端监听和防火墙状态
进入服务器执行:
sudo ss -tlnp | grep 22 systemctl status ssh sudo ufw statusss能看到sshd监听在哪个IP和端口。如果只监听了127.0.0.1而没监听0.0.0.0,说明sshd配置里设置了只允许本机回环访问,外部肯定连不上。这种情况在WSL里很常见,需要检查ListenAddress配置。
ufw是ubuntu自带的防火墙。如果状态是active且没有放行22端口,外部连接会被静默丢弃。放行命令:
sudo ufw allow 22/tcp如果你用的云服务器,还需要去云控制台的安全组里把22端口入方向放行,这一步是云上环境排兵布阵的重点,甚至比服务端本身更经常出问题。
4.3 第三步:在服务器本机测试SSH登录是否正常
在ubuntu服务器本机执行ssh 用户名@localhost,如果本机也需要密码且能登录成功,说明用户密码和sshd基础配置没问题。如果本机也登录失败,你可以直接锁定问题在服务端用户或配置,不必再去折腾网络。
如果本机能正常登录,外面的FinalShell却不行,那就要回到服务端配置看向外的监听、防火墙、云安全组,以及是否限制了AllowUsers。
AllowUsers是一个容易被忽略的配置。如果sshd_config里写了AllowUsers ubuntu,那么即使你密码正确,其他用户名也会被拒绝。查一下:
grep -i "AllowUsers\|AllowGroups" /etc/ssh/sshd_config /etc/ssh/sshd_config.d/4.4 第四步:完整检查PAM和登录限制
ubuntu的SSH登录还受PAM(可插拔认证模块)影响。如果你发现密码明明正确,但登录时日志里出现pam_unix(sshd:auth): authentication failure,那除了密码错误之外,还可能涉及账户锁定、密码过期、家目录权限等问题。
一个常见的情况是用户家目录权限异常。SSH登录时,sshd需要读取~/.ssh/authorized_keys,如果家目录对其他用户是可写的,OpenSSH出于安全考虑会拒绝使用公钥认证,而且表现为认证失败。修正方法:
chmod 700 /home/用户名 chmod 700 /home/用户名/.ssh chmod 600 /home/用户名/.ssh/authorized_keys这一步虽然不是“密码登录”的直接原因,但如果你一会儿要配密钥做免密,权限不对绝对会让人怀疑人生。
4.5 第五步:按表格快速定位
我把整个排查过程整理成一张表,方便你对照自己的现象快速判断。
| 现象 | 可能原因 | 检查命令/位置 | 解法 |
|---|---|---|---|
| Connection refused | ssh服务未装/未启动 | systemctl status ssh | 安装并启动openssh-server |
| Connection timed out | 防火墙/安全组拦截 | sudo ufw status、云控制台 | 放行22端口 |
| 提示密码错误(命令行也失败) | 密码真实错误 | /var/log/auth.log | 重置密码 |
| 提示密码错误但本机可登录 | sshd限制 | grep AllowUsers | 注释限制或用对应用户名 |
| 密码正确但root连不上 | PermitRootLogin限制 | sshd -T | grep permitrootlogin | 设置PermitRootLogin yes |
| FinalShell弹窗但命令行可连 | 客户端密钥优先/配置异常 | FinalShell认证方式 | 改为密码认证,清空密钥 |
| 密码框循环弹出 | 主机密钥缓存 | FinalShell安装目录 | 删除known_hosts缓存 |
这张表虽然不能覆盖所有情况,但覆盖了我在实际工作中遇到的九成以上问题。
5. 从修好密码到顺手配置密钥登录:后期一步到位
问题修好之后,很多人下一步就是配密钥免密登录,省得每天输密码。这个操作本身不难,但里面有几个细节如果不注意,又会回到“输密码输不对”的老路上。
5.1 生成密钥对并上传公钥
在Windows命令行或FinalShell的“工具”菜单里都可以生成密钥对。生成后,需要把公钥内容放到服务器的~/.ssh/authorized_keys文件里。手工复制容易出错,推荐直接用命令:
ssh-copy-id 用户名@服务器IPWindows没有这个命令的话,可以用:
type $env:USERPROFILE\.ssh\id_rsa.pub | ssh 用户名@服务器IP "mkdir -p ~/.ssh && cat >> ~/.ssh/authorized_keys"注意这里输入密码时用的是当前用户密码,如果在这一步就提示密码错误,说明上面几个环节还没彻底修好,先不要继续往下配。
5.2 权限问题直接决定密钥是否生效
公钥放上去之后,必须确保.ssh目录和authorized_keys文件权限正确。刚拷贝过去的文件,从用户目录到文件每一层都要检查:
chmod 700 ~/.ssh chmod 600 ~/.ssh/authorized_keys如果权限是755或者文件其他用户可写,sshd会拒绝使用这个公钥,表现就是依然要求输入密码。这也是“为什么我明明配了密钥还是提示密码”的最常见答案。
5.3 FinalShell里如何正确添加私钥
私钥放在Windows本地之后,在FinalShell的会话属性里找到“认证”Tab,选择“公钥”,然后浏览并选中你本地的私钥文件。如果私钥创建时设置了口令(passphrase),连接时会要求输入这个口令,而不是登录用户名密码。
这里很多人会搞混:FinalShell要求输密码,到底是用户密码还是密钥口令?如果你明确看到连接时选了密钥认证,那么弹窗里输入的应该是创建密钥时设置的口令,而不是服务器登录密码。如果当时没设置口令,就应该一路回车不填,如果此时你填了用户密码,反而会认证失败。
5.4 顺手加固:修改默认端口可以少挨扫描
如果你用的是云服务器,公网IP会持续被扫描,22端口是重灾区。建议在服务端修改/etc/ssh/sshd_config里的Port为一个不常用的高位端口,比如 22222,然后同时修改云安全组和FinalShell会话端口。改完之后重启ssh服务,再用新端口重新连接验证一次。
修改端口这个操作有个前提,就是防火墙要放行新端口,千万不要改完端口把自己锁在门外。稳妥做法是先把新端口加进ufw和安全组,再重启ssh,确认能连上之后再考虑要不要关掉22端口。
配置示例:
sudo ufw allow 22222/tcp sudo sed -i 's/#Port 22/Port 22222/' /etc/ssh/sshd_config sudo systemctl restart ssh连接测试:
ssh -p 22222 用户名@服务器IP成功之后再决定是否移除22端口的放行。生产环境建议保留密钥登录,关闭密码登录,这样以后再也不会有“FinalShell一直提示密码”的问题——不是因为它再也不弹密码了,而是根本不需要密码了。
6. 那些年我踩过的FinalShell和SSH密码坑
文章最后,分享几个我自己实际经历过的特殊案例,给遇到“玄学问题”的朋友一些参考。这些案例在常规文档里基本看不到,但确实真实存在。
第一个案例是FinalShell版本太旧导致的认证异常。我有一次给一台ubuntu 22.04的机器配SSH,同一个服务器,用系统自带的OpenSSH命令行连接一切正常,用FinalShell就是反复提示密码。后来我更新了FinalShell到最新版,问题立刻消失。分析原因,老版本FinalShell对OpenSSH新版本打开的某些密钥交换算法支持不到位,导致认证流程中断。如果你遇到了“命令行能连、FinalShell不能连”的诡异情况,先把FinalShell升级到最新版再说。
第二个案例是服务器时间不同步导致的认证异常。Kerberos或者某些需要时间戳校验的认证方式对时间敏感,但纯密码认证一般不在意。不过ubuntu的PAM在配置了某些模块时,时间偏移过大也可能异常。遇到密码确认正确但登录时有时无的情况,可以跑一下timedatectl,顺手把时间同步打开,是个低成本高回报的排查动作。
第三个案例是WSL环境下连Windows本地目录的问题。很多人用WSL跑ubuntu,然后尝试从FinalShell连WSL的IP,发现无论如何都提示密码或者直接超时。WSL2默认网络是NAT模式,从Windows宿主机连接WSL2需要走localhost:22或者配置networkingMode=mirrored,直接填WSL内部的IP经常连不上。这不是密码问题,是网络模式本身限制了访问。如果你的FinalShell怎么都连不上WSL,先检查WSL版本和网络配置,别在密码上耗时间。
第四个案例,也是最容易被忽视的:有人把FinalShell的“保存密码”功能当成密码保险箱,密码填错一次,工具也会保存下来,下次连接直接使用错误的旧密码,根本不给你重新输入的机会。看起来像“一直提示密码错误”,其实是它一直在自动提交错误密码。解决办法就是在会话属性里强制清空已保存的密码,再手动输入一遍正确密码,必要时把“记住密码”勾选去掉。
这些案例说明一个道理:FinalShell通过SSH连接ubuntu一直提示密码,不是单一原因,而是一系列配置和工具行为的叠加结果。排查时不要急躁,从网络层、服务层、认证层、客户端层一路走下来,绝大多数人最终都能找到那个真正让自己卡住的地方。我在实际排查中最大的体会是:先把“密码”两个字从脑海里拿掉,去查服务、查配置、查认证方式,答案通常比想象中简单很多。