干这行最怕什么?不是系统崩了,不是流量被打满,而是某天登录服务器时,发现自己把root密码给忘了。机房连夜跑过去,Console接上,屏幕亮着,手边一堆维护手册,却连系统都进不去。我在过去几年运维经历里,至少在四五台CentOS、Ubuntu和嵌入式板卡上干过这种"重置root密码(root密码破解)"的活儿,深知这事看起来像玄学,掰开揉碎其实就是一套启动参数与根文件系统挂载的博弈。这篇文章就把这套方法从原理到实操讲透,覆盖RHEL系、Debian系和嵌入式Linux三大场景,顺带把重置之后密码过期、安全加固这些收尾事项也一并说清楚。适合所有手里有Linux设备、做过系统管理、或者动不动就把密码忘在脑后的同行参考。
1. 先把思路理清楚:重置root密码靠的是什么原理
1.1 你绕不开的shadow文件与PAM认证链路
Linux的root密码并不是存成明文,而是经过加密后写在 /etc/shadow 这个文件里。root用户登录时,系统会走PAM认证链路,比对你输入的密码经过相同hash处理后是否与shadow里的记录一致。理解了这条链路,所谓的“忘记root密码”就变成了一个问题:在有物理访问或者管理控制台权限的前提下,怎么把一个我们知道的密码写进 /etc/shadow。
实际操作里无非两条路线:要么让系统以特殊方式启动,进入一个不需要完整登录流程的root shell;要么通过Live CD等外部系统,把原来的根分区挂载上来,直接修改shadow文件。两条路线的本质都是“在root身份下改shadow”,区别只在于怎么拿到这个root shell。
1.2 几种重置方案的适用边界
网上流传的方法不少,单用户模式、救援模式、rd.break、init=/bin/bash,听着都差不多,但各自适用场景完全不同。
| 方案 | 适用系统 | 核心思路 | 踩坑风险 |
|---|---|---|---|
| 单用户模式 | SysVinit老系统、部分systemd系统 | 以单用户进入默认runlevel | systemd下可能仍需输入密码,兼容性差 |
| rd.break | RHEL/CentOS 7/8/9、Fedora | 打断dracut初始化流程,在initramfs阶段进入shell | 需要手挂根文件系统,SELinux标记需处理 |
| init=/bin/bash | Ubuntu/Debian、部分嵌入式 | 内核直接拉起bash,跳过systemd与登录流程 | 需手动把根分区变成可读写 |
| Live CD/USB chroot | 几乎全系列 | 外部系统挂载根分区后chroot修改 | 需要准备启动介质,对LUKS加密盘无能为力 |
| uboot传参 | 嵌入式Linux | 通过bootloader给内核传不同参数 | 不同板卡差异大,只读rootfs需额外处理 |
清楚边界之后,出问题时才不会手忙脚乱。下面分开讲我最常用、也最推荐掌握的三套打法。
1.3 一台“能物理访问”的机器是前提
有一点必须说明,所有重置手段都有一个隐含前提:你能接触到设备的控制台。不管是通过iDRAC/IPMI这样的带外管理,还是直接跑到机房接显示器,在虚拟化平台上则是通过VNC/Console窗口。换句话说,你要么物理掌控设备,要么虚拟化控制台在你手里。如果你面临的是远程SSH断连、又没有带外管理通道的情况,那真心建议平时就把sudo备份账户、密钥对这类逃生通道留着,别等锁死了再想办法。除了合法管理员对自己或本单位授权设备进行恢复的场景之外,任何针对他人系统的“破解”行为都是违规的,这点必须守住。
2. RHEL/CentOS系最顺手的rd.break重置法
2.1 从GRUB菜单到dracut shell的完整路径
CentOS 7之后,系统启动用的是GRUB2,内核由GRUB先加载,接着进入initramfs(也就是dracut生成的initramfs镜像),这个阶段负责加载磁盘驱动、组装根设备、准备切换到真正的根文件系统。rd.break要打断的就是这个流程,让我们停在根文件系统尚未完全挂载好的dracut shell里。
具体操作:
- 重启系统,出现GRUB菜单时,选中默认内核那一项,按 e 进入编辑模式。
- 找到以 linux16 或 linux 开头的那一行(通常是很长的一行,里面包含 root=、rhgb、quiet 等参数),把光标移到行尾,留一个空格,追加 rd.break。
- 按 Ctrl+X 或 F10 启动。系统会在initramfs阶段停下来,进入一个提示符类似 switch_root:/# 的shell。
这个shell环境已经很接近目标系统了,但此时真正的根文件系统其实挂在 /sysroot 目录下,而且大多情况下是只读状态。如果你直接执行 passwd,大概率会报错。所以下一步的挂载操作是必做项。
2.2 mount、chroot、passwd三步交接
进入switch_root shell后,依次执行以下命令:
switch_root:/# mount -o remount,rw /sysroot switch_root:/# chroot /sysroot bash-4.2# passwd root第一句是把 /sysroot 重新以读写方式挂载。为什么要重挂载一次?因为initramfs阶段为了文件系统一致性,默认以只读方式挂载,不重挂的话后续所有写操作都不会生效,而且系统不会给你任何直观报错,很多新手在这上面莫名其妙卡很久。
第二句 chroot /sysroot 意思是把根目录切换成目标系统真正的根文件系统。执行之后,你现在看到的 /etc、/home、/var 就是原来系统里的目录了,passwd、chage 这些命令也换成了目标系统里的版本。
第三句就是常规修改root密码:
Changing password for user root. New password: Retype new password: passwd: all authentication tokens updated successfully.输入两遍新密码即可。这里建议把密码复杂度设置得有点样,至少包含大写、小写、数字和特殊字符。重置密码后要退出chroot,但别直接重启,先处理SELinux的问题。
2.3 SELinux那一步为什么不能省
RHEL系默认开启SELinux,因为修改/etc/shadow并不经过正常的会话流程,新写入的文件可能没有正确的SELinux安全上下文,或者上下文标记不匹配。这时候如果有一步没做,重启后系统很可能陷入一个很尴尬的状态:SELinux报错、登录卡住、服务起不来,甚至可能出现密码改好了却始终认证失败的情况。
正确的收尾操作是在chroot环境里执行:
bash-4.2# touch /.autorelabel这个空文件的作用是告诉系统,下次启动时对整个文件系统做一次SELinux重新标记。标记过程会花几分钟,服务器配置差的可能要十几分钟,屏幕上会有红色的百分号进度提示,别看到进度条就走开了,等它跑完自动重启。如果你确定当前系统根本没开SELinux,那这步可以跳过,但对企业里跑着业务的机器,我从来都是无脑touch,反正只是多等几分钟,稳比快重要。之后依次输入 exit 退出chroot,再 exit 退出switch_root shell,系统会继续原来的启动流程。
2.4 我遇到过的几个意外情况
这个方案我用了很多次,成功率很高,但也不是没有意外。
第一是输入 rd.break 后直接卡在缺少驱动的地方。这种情况多见于特殊硬件阵列卡或NVMe设备,由于intramfs本身驱动缺失,无法识别根设备。此时先在BIOS/直通模式确信磁盘能被系统识别,或者换一个带完整驱动的救援ISO来完成操作。
第二是执行 passwd 时提示 token manipulation error。这个报错多半是文件系统还挂在只读模式,又或者/etc/shadow本身权限异常。可以用 mount | grep sysroot 确认挂载状态,再用 ls -l /etc/shadow 和 /etc/passwd 检查owner是否root。正常权限shiki,shadow文件owner为root、group为root、权限为000或640。
第三是完成后重启,系统一直停在SELinux的relabel过程,看起来像卡死。其实只要它停留在Auto-relabeling阶段,耐心等就好,我的经验是普通机器5到10分钟就结束,如果超过20分钟还不动,再考虑是不是有文件系统损坏。中间千万不要强行断电,否则后果更难收拾。
3. Ubuntu/Debian系:init=/bin/bash与Live USB双保险
3.1 修改GRUB启动参数进入“无systemd”的root shell
Ubuntu这个系最大的特点是用initramfs阶段后直接交给systemd,但如果我们不想经过systemd,可以直接在GRUB里让内核拉起一个bash,绕开系统初始化里所有可能卡住的服务,U、过期策略,全部用chage把策略落到具体身份组上,还可以把自动过期提醒写进登录后的mcotd脚本。
5.2 为什么我始终建议关掉root远程密码登录
密码重置是“最后手段”,但如果你把root当成日常登录账户且开着密码登录,那等于把最后手段也变成了攻击面。即使密码设成,Tr0ub4dor&3这种,在公网上风险依然不小,因为攻击者可以无限次尝试并利用各种漏洞提权。
我现在的习惯是:ssh直接禁止root密码登录,sshd_config里把PermitRootLogin设为prohibit-password,同时给管理员账号配置SSH密钥。root密码只留到本地控制台或带外管理时使用。这么一改,就算远程被人扫到SSH端口,没有私钥也进不来,root远程爆破的威胁直接归零。这套配置在绝大多数发行版上都通用,改完记得 systemctl restart sshd 或 service ssh restart。
5.3 日志里那些“反复失败的登录尝试”意味着什么
重置完密码后,我还会顺带看一眼 /var/log/secure(RHEL系)或 /var/log/auth.log(Debian系)里的Failed password记录。不要小看这些日志,它们经常能提前告诉你哪台机器被爆破盯上了,哪些IP在反复试探。如果发现大量来自陌生IP的暴力尝试,除了确认密码强度,还应该考虑装fail2ban或者干脆把SSH端口从22改成高位端口。
6. 最后一篇:几个容易在本故障中踩中的隐形坑
6.1 LUKS全盘加密会让所有重置方法失效
如果系统安装时开启了全盘加密(LUKS),rd.break和init=/bin/bash全都无用,因为根分区数据在解密前根本看不到。这种机器最稳妥的办法是在解密之前进入救援环境,用已知的LUKS passphrase挂载加密卷后再chroot改密码。也就是说,如果生产环境用了LUKS,你的“最后一根救命稻草”取决于LUKS密码是否还记得——别再把它和root密码一起忘掉了。
6.2 fstab异常会自动把你送到emergency mode
有些机器在重启重置密码时,会因为/etc/fstab里某个挂载项失效而自动进入emergency mode,屏幕上还提示输入root密码。如果你刚重置过密码,用新密码尝试进不去的概率不低,原因可能是SELinux上下文未更新或者shadow文件权限异常。这时候就老老实实按Ctrl+D让它继续尝试,多半能绕过,或者在emergency shell里手动检查 /etc/fstab 和挂载状态。
6.3 BIOS密码挡住你进GRUB编辑
还有一个你猜不到的问题——很多服务器BIOS/固件层面就设置了开机密码,GRUB编辑功能也被锁住。这就导致即使你知道所有Linux层的骚操作,根本走不到修改启动参数那一步。遇到这种情况,只能联系机房或设备提供方处理固件密码,没有任何软件层面的捷径。所以企业在物理机运维交接时,固件密码的交接往往比系统密码更重要。
6.4 别忘了“都重置完之后验证一遍”
每次重置完root密码,我都不急着关console。重启到登录界面后,先SSH远程登录一次,再本地控制台登录一次,确认业务关键服务都正常起来,最后把新密码写进密码保险库,才算真正结束。很多故障之所以演变成“二次事故”,就是重置密码后太乐观,忘了验证,结果业务半夜起来报错,人又得回机房跑一趟。
末尾的一点经验
重置root密码这件事本身不难,难的是把整套流程想周全。我在实际操作中体会到,每一次重置都是一次对整个环境敏感度的审视——分区加密没有、SELinux关没关、系统有没有接带外管理、日志是否在正常记录。如果你在平时就愿意花半小时把这些情况摸清楚,真到了深夜炸机房的时候,心里是有底的。最后再分享一个小技巧:处理完这类问题,顺手把操作时间、使用的方法、遇到的异常都记进运维手册,哪怕只是几句话,下一次再碰上同样问题,翻笔记比重新踩坑快得多。