
1. Ubuntu为什么默认锁死root远程登录拿到一台全新的Ubuntu服务器很多人第一件事就是拿旧环境的root密码去SSH登录结果迎面一句Permission denied。这真不是密码输错了Ubuntu在root账号和SSH服务两个层面各自设了一道锁两道锁叠在一起才形成了你看到的“死局”。想打开root登录得先把这两道锁的来龙去脉弄清楚。1.1 root账号本身没有密码Ubuntu安装过程中并不会让你设置root密码系统装完之后root账号实际上处于“锁定”状态日常操作一律通过sudo完成。这是从其他发行版转过来的用户最容易忽略的一环别的系统装完可以直接root登录Ubuntu这里连在本地终端里输入root密码都是进不去的。你可以用下面这条命令查看root账号的真实状态sudo passwd -S root正常情况下输出结果类似这样root L 01/01/2024 -1 -1 -1 -1 0000 -1看到大写字母L说明root账号是锁定的。想解锁最直接的方式就是给它设置一个密码sudo passwd root这一步是整个流程的前提条件。如果root没有可用密码就算后面把sshd配置改成PermitRootLogin yes登录时也会提示密码认证失败因为系统里压根不存在可以通过认证的root密码。1.2 sshd层面还有第二道闸门即使root有了密码SSH服务端默认也不会放行。OpenSSH从7.0版本开始把PermitRootLogin的编译默认值改成了prohibit-password含义是允许root使用公钥登录但禁止root使用密码登录。Ubuntu自带的/etc/ssh/sshd_config里也保留了对应注释行#PermitRootLogin prohibit-password注意这一行是被注释掉的也就是说系统没有做显式配置但OpenSSH内部默认值就是prohibit-password实际效果等同于启用了这一行。网上不少教程说“取消注释改成yes就行”这只说对了一半——配置文件改了但root没有密码照样进不去。所以完整的逻辑是先在系统层面给root准备一个可用的认证方式也就是密码或公钥再在sshd层面放开root登录权限。两个条件缺一不可。下面我会先从密码登录这条线路把整套流程跑通再说怎么收尾加固。2. 动手之前版本确认、密码准备和配置备份改SSH配置属于高危操作出问题直接连不上机器。每次动手之前我会老老实实花上几分钟做环境确认和备份这些习惯能帮我省掉大量排错时间。2.1 先花两分钟确认系统和SSH版本确认Ubuntu版本cat /etc/os-release确认OpenSSH版本sshd -V目前主流的Ubuntu 20.04、22.04、24.04都适用我下面要讲的配置方式更早的16.04、18.04也能用只是在新版本新增的Include目录和云镜像预置配置上略有差异排查章节我会单独展开。版本信息记下来后续看日志、查文档时心里有数。2.2 给root设置密码这一步很多人会漏前面说过Ubuntu默认root是锁定状态。执行sudo passwd root系统会要求先输入当前sudo用户的密码然后连续两次输入root的新密码。看到passwd: password updated successfully就说明设置成功账号也随之解锁。这里有个容易误解的点sudo passwd root和sudo passwd -l root是相反操作前者是设密码、解锁后者是给密码字段加锁标记、锁定账号。如果你之前做过安全加固锁过root后面无论怎么改sshd配置都不可能用密码登录排查时别忘了这一层。2.3 备份配置并注意Include目录的覆盖规则改配置前备份是基本操作别嫌多余。我在每台服务器上都这么干sudo cp /etc/ssh/sshd_config /etc/ssh/sshd_config.bak.$(date %F)备份文件名带日期方便日后回滚时快速识别。另一个重要细节Ubuntu 22.04及之后版本的sshd_config开头通常会有一行Include /etc/ssh/sshd_config.d/*.conf这句话会让/etc/ssh/sshd_config.d/目录下所有.conf文件参与配置合并。由于Include出现在文件最顶部按OpenSSH“先到先得的参数生效规则”这个目录里的配置优先级反而高于主配置文件后面写的任何内容。云厂商的Ubuntu镜像经常会在该目录下放一个50-cloud-init.conf里面可能写着PasswordAuthentication yes或PermitRootLogin no之类的覆盖项。如果后面怎么改主配置都不生效先去这个目录翻一翻问题多半出在这里。2.4 留一条绝对安全的回退通道改SSH配置时最怕的是自己在服务器上改了配置并重启服务结果新配置有语法错误导致服务起不来自己又被踢出会话只能眼巴巴地去控制台抢救。我的习惯是动手之前确保至少还有一个已登录的SSH会话窗口不关闭或者确认自己能打开云厂商的网页控制台。配合下面要讲的语法检查基本就不会把自己锁在门外。3. PermitRootLogin四种取值选哪个直接决定能否登录这是整篇文章最核心的参数。PermitRootLogin共有四种取值每一种的行为差异很大网上很多教程把它们混在一起讲我整理了一张对照表。3.1 四种取值的真实行为对比取值密码登录公钥登录实际含义yes允许允许完全放开所有认证方式都接收prohibit-password禁止允许密码方式对root关闭公钥照常OpenSSH 7.0起的内置默认值without-password禁止允许prohibit-password的旧写法语义相同现在仍兼容no禁止禁止彻底关闭root远程登录完全锁死如果你只想跑通“root能用密码直接SSH”那就要改成yes。但我要提醒一句让root密码直接暴露在公网SSH端口上等于给全世界的扫描器留了一个极其显眼的目标。我更推荐的做法是先用yes把流程验证通过确认没问题后马上改回prohibit-password只保留公钥认证这一条路。后面我专门用一节讲加固这里先把能跑通的配置做出来。3.2 prohibit-password和without-password的纠葛很多老教程写的是without-password新文档里写的是prohibit-password这俩其实是同一个意思只是OpenSSH在不同版本换了更明确的叫法。without-password字面上容易让人误解成“不需要密码”实际是“不允许root用密码登录”只允许密钥。看到老配置里有这个值时别慌直接改成新写法prohibit-password或者保持原样都可以行为不会变。还有一个冷知识在OpenSSH 7.0之前PermitRootLogin的默认值其实是yes也就是老系统默认允许root密码登录。如果你维护的是一台很老的服务器需要先确认它实际用的OpenSSH版本再判断默认行为不要想当然。3.3 密码登录的总开关PasswordAuthentication很多人只盯着PermitRootLogin忽略了另一个总开关PasswordAuthentication。真正的密码认证流程要求两个参数同时放行PermitRootLogin yes决定root能不能登录PasswordAuthentication yes决定系统允不允许使用密码这种认证方式。看两个组合就清楚了PermitRootLogin yesPasswordAuthentication yesroot可以用密码登录。PermitRootLogin prohibit-passwordPasswordAuthentication yes普通用户可以密码登录但root不行root只能用密钥。Ubuntu默认PasswordAuthentication是开启的但如果你之前为了安全手动关过它就算root权限全放开也没用。排查问题时一定要两个参数一起检查。4. 从改配置到验证登录的完整流程下面给出一套可以直接照抄的命令流程以Ubuntu 22.04为例。整套流程的核心思路是“小步走、随时能回退”每一步都有对应的验证手段。4.1 修改sshd_config打开主配置文件sudo nano /etc/ssh/sshd_config找到这一行#PermitRootLogin prohibit-password如果只是想让root能密码登录把它改成PermitRootLogin yes如果目标是用密钥登录root改成PermitRootLogin prohibit-password保存退出。注意不要在文件里写多个PermitRootLogin按先到先得的规则只有第一个出现的值会生效多个值只会让后续维护的人一头雾水。改动之前最好再用注释注明改动日期和原因生产环境的配置文件最怕留无头账。4.2 重启前必做的语法检查这一步绝对不能省。执行sudo sshd -t没有任何输出说明配置语法正确。如果返回类似这样的报错/etc/ssh/sshd_config line 32: Bad yes value说明第32行有拼写或格式问题回去改好再试。sshd -t只做语法检查不会影响正在运行的服务可以反复执行放心用。它是我在任何一次SSH配置变更前都必须执行的动作养成习惯之后因配置写坏导致服务起不来的概率会无限趋近于零。4.3 重启服务注意Ubuntu的服务单元名Ubuntu的SSH服务单元名是ssh.service不是sshd.service。执行sudo systemctl restart ssh重启后确认状态sudo systemctl status ssh看到active (running)就说明服务正常起来了。如果你在配置里引入了语法错误这里会直接看到failed状态这时候用之前的备份文件恢复配置再重启一次就能救回来。这里还有个细节值得提一下systemctl restart ssh是重启systemctl reload ssh是让服务重新加载配置而不中断现有连接。如果你在服务器上还有别的重要会话用reload更温和。但为了确保配置彻底生效我一般还是用restart因为有些参数在reload时并不会重新读取。4.4 用新终端的实际登录作为最终验证在你自己的电脑上打开一个新终端执行ssh root服务器IP输入刚设置的root密码能进入root shell就说明整条链路已经打通。如果提示Permission denied先别慌下一节就是完整的排查路径。验证成功、确认不再需要临时调整后记得回到配置里把PermitRootLogin改回prohibit-password再重启一次服务后续登录就改用密钥。“临时打开-验证-收紧”这套流程我在很多台服务器上反复实践过既保证了任务能完成又把暴露时间压到了最短。5. 配置改完还是登不进去的排查链路这一节可能是本文最有实用价值的部分。我见过太多人卡在“明明改对了也重启了为什么还是进不去”。这类问题有一个典型的排查顺序按下面的链路走通常几分钟就能定位。5.1 用sshd -T查看实际生效值不要只盯着配置文件要确认sshd真正加载了什么。执行sudo sshd -T | grep -i permitrootloginsshd -T会把最终生效的配置逐项输出需要root权限才能看全。如果输出结果是prohibit-password而你明明在文件里写了yes说明一定有个地方把它覆盖了。优先检查sshd_config顶部的Include行以及/etc/ssh/sshd_config.d/目录下的所有.conf文件云镜像里的50-cloud-init.conf是头号嫌疑。这种“配置文件写了但实际没生效”的情况靠肉眼看文件几乎永远找不出来用sshd -T一秒钟就现原形。5.2 检查root密码状态继续用这一条命令sudo passwd -S root前面说过看到大写L说明账号锁定。需要重点排查两种场景一是你从未设置过root密码二是之前为了安全执行过passwd -l root后来忘记了。这两种情况下无论PermitRootLogin设成什么密码登录都不可能成功。重新执行sudo passwd root设一遍密码即可。5.3 公钥登录失败的权限排查如果把PermitRootLogin设成了prohibit-password却依然登录失败并且错误提示只有Permission denied (publickey)重点检查以下几项/root目录权限不能是775或777标准做法是chmod 700 /root/root/.ssh目录权限必须是700/root/.ssh/authorized_keys文件权限必须是600文件属主必须是root:root。还有一个常见低级错误在Windows上生成的公钥粘贴进authorized_keys时带上了多余空格或换行导致密钥格式损坏。遇到这种情况可以在服务器端执行ssh-keygen -l -f /root/.ssh/authorized_keys这条命令会列出文件里所有公钥的类型和指纹。如果正常输出说明密钥格式没问题如果报错说明文件内容需要重新整理。5.4 用auth.log定位问题环节Ubuntu的SSH登录日志写在/var/log/auth.logsudo tail -n 100 /var/log/auth.log也可以实时跟进sudo journalctl -u ssh -f日志里的几类关键词能帮你快速缩小范围Failed password for root密码认证流程已经走通只是密码不对。user root not allowed because account is locked认证阶段过了但系统层账号是锁的。Connection reset by peer多半是网络或防火墙层面直接掐断了连接跟SSH配置无关。日志永远是最直接的排错入口别一上来就盲目改配置先看日志能省下大量时间。6. root登录打开之后的加固方案配置做完只是第一步更重要的课题是如何降低风险。root远程登录一旦带着密码开放任何直接暴露在公网上的服务器都等于挂了个醒目的靶子。我写这篇不是鼓励大家无脑开root而是要把这个操作的正确姿势讲明白。6.1 生产环境推荐配置只开密钥关掉密码落地时我会把SSH配置收敛成这个组合PermitRootLogin prohibit-password PasswordAuthentication no PubkeyAuthentication yes这样root只能通过密钥登录普通用户也不能再使用密码登录暴力破解的入口基本上被堵死了。如果有多人需要登录服务器各自把公钥放进~/.ssh/authorized_keys配合sudo来管理权限比共享root密码干净太多出了问题也更好追责。6.2 用Match限定来源IP如果某些场景确实需要root能密码登录也别对所有IP开放。可以限定只有可信来源才能这样做PermitRootLogin prohibit-password Match Address 192.0.2.25 PermitRootLogin yes这段配置的意思是默认情况下root只能用密钥登录只有来自192.0.2.25这个IP的会话允许root使用密码。需要特别注意的是Match块必须放在配置文件末尾Match之后的所有参数都会作用于匹配到的会话位置放错了会导致后面的全局配置全部失效。用这个方式就算密码泄露攻击者也无法从其他IP利用它登录root。6.3 用fail2ban把暴力破解挡在门外给SSH加一道自动封禁的保险丝我每台公网服务器都会装fail2ban成本极低sudo apt update sudo apt install fail2ban默认配置就会监控sshd连续失败次数超过阈值的IP会被临时封禁。想调整参数编辑/etc/fail2ban/jail.local[sshd] enabled true maxretry 3 bantime 3600重启服务生效。另外云厂商的安全组或防火墙策略里也建议加一条SSH端口只对你自己常用的IP段开放。软件层和网络层双保险的效果远好于只依赖其中任何一个。6.4 几个我一直在用的日常习惯root登录打开后我自己一直坚持这几件事定期查看/var/log/auth.log里有没有大量Failed password记录设置root密码时使用足够复杂的强密码绝不用生日、机器名这类弱口令长期用不到的root密码登录方式确认不再需要后立刻重新锁死sudo passwd -l root锁定之后root无法再通过密码远程登录但sshd服务不受影响普通用户和已配置好的密钥登录都能继续正常工作。这套习惯让我在维护了多台服务器之后依然能有效控制root账号的暴露面。最后说一点我持续在执行的心得。处理过的服务器里真正长期开着PermitRootLogin yes的基本没有绝大多数场景下prohibit-password加密钥登录已经足够。遇到必须root直连的初始化任务我都是临时改为yes、重启、干完活、立刻改回prohibit-password、再重启整个过程不超过十分钟。这套办法看起来有点繁琐但帮我躲过了不止一次因配置遗留而引发的暴力破解风险。照着本文的流程走一遍你也能把“打开root登录”这件事做得既通又稳。