救援模式:把自己锁在服务器外面之后如何修复

sshd 配置写坏、防火墙规则把自己拦在门外、磁盘写满,或者 fstab 里有一行出错:如何启动救援模式、挂载磁盘并修复问题。

C工CheapServ 工程团队作者 6 分钟阅读
一只发光的救生圈,漂在一台服务器旁边
本页目录9
  1. 救援模式做了什么
  2. 挂载磁盘
  3. 修复 1:损坏的 sshd 配置
  4. 修复 2:误伤自己的防火墙规则
  5. 修复 3:磁盘被写满
  6. 修复 4:错误的 fstab 条目
  7. 救援模式的其他用途
  8. 退出救援模式
  9. 防患于未然

每位管理员迟早都会把自己锁在服务器外面:sshd_config 里的一处笔误,一条把 22 端口也拒之门外的防火墙规则,一块一夜之间被写满的磁盘,fstab 里指向某个已不存在的卷的那一行。救援模式就是为这样的早晨准备的。它通过网络启动一个 Live 系统,您的磁盘原封不动,您可以挂载磁盘、修好出问题的那一行,然后重启回到一台正常运行的服务器。本文介绍救援模式的用法,以及能覆盖大多数情况的四种修复方法。

救援模式做了什么

在服务器的电源选项卡中点击进入救援模式,服务器会重启并进入一个通过网络加载的、基于 Debian 的小型镜像。您的磁盘不会被修改,也不会被挂载;救援系统完全运行在内存中。它自带 SSH,并已预装您在控制面板中设置的密钥,同时提供常用工具(mount、chroot、fsck、mdadm、cryptsetup、zfs、各类编辑器)和网络访问。如果被您搞坏的恰恰是 SSH,也可以使用控制面板里的控制台。退出救援模式只是一次普通的重启;救援模式开启期间,控制面板会显示一条横幅,免得您忘记。

在做任何其他事情之前,如果还能创建快照,请先在控制面板里创建一个。如果已经无法创建(服务器已经处于救援模式),那么在您往磁盘写入数据之前,磁盘依然是安全的;请谨慎操作。

挂载磁盘

lsblk -f                                # find the root partition: usually vda2 (VPS) or md0 / nvme0n1p2 (dedicated)
mount /dev/vda2 /mnt
mount /dev/vda1 /mnt/boot               # if /boot is separate; on UEFI images: /mnt/boot/efi
for d in dev proc sys run; do mount --rbind /$d /mnt/$d; done
chroot /mnt /bin/bash                   # you are now "inside" your server, without running it

如果是做了软件 RAID 镜像的独立服务器,请先执行 mdadm --assemble --scan,再挂载 /dev/md0;如果是 ZFS,执行 zpool import -f -R /mnt rpool 就能一次性把所有文件系统都挂载好。

修复 1:损坏的 sshd 配置

sshd -t -f /mnt/etc/ssh/sshd_config      # from outside the chroot: prints the offending line
nano /mnt/etc/ssh/sshd_config.d/10-hardening.conf

常见的罪魁祸首有:把后面所有选项都“吞”进去的 Match 块;在密钥装好之前就写上的 PasswordAuthentication no;或者改了端口却没有放行对应的防火墙规则。改好出错的那一行,用 sshd -t 再检查一遍,然后重启。

修复 2:误伤自己的防火墙规则

chroot /mnt ufw disable                 # ufw: turns it off at next boot; re-enable after fixing the rule
nano /mnt/etc/nftables.conf             # nftables: remove or fix the rule, keep the file valid
rm /mnt/etc/iptables/rules.v4           # iptables-persistent: drop the saved rules entirely

重启后登录,补上缺失的 allow 22/tcp(或您自己的端口),再重新启用防火墙。如果您的防火墙由 cloud-init 或 Ansible 管理,请连源头一并修正,否则下一次运行时又会把您锁在门外。

修复 3:磁盘被写满

du -xh --max-depth=2 /mnt | sort -h | tail -20    # where did it go?
journalctl --root=/mnt --vacuum-size=200M          # systemd journal, a common offender
rm -rf /mnt/var/lib/docker/tmp/*                   # or prune from inside after boot
find /mnt/var/log -name '*.gz' -delete             # rotated logs are safe to remove

腾出几个 GB 的空间,重启,然后再去根治原因:日志轮转、往本地写数据的备份脚本、没有保留策略的数据库。只要病根还在,磁盘被写满到 100% 的情况下个月还会重演。

修复 4:错误的 fstab 条目

如果 /etc/fstab 中引用了一个不存在的卷,而且没有加 nofail 选项,启动就会停在一个您无法进入的紧急 shell 上。把那一行注释掉,或者给它加上 nofail,x-systemd.device-timeout=10,然后重启。每一个非根分区的挂载项都应该带上 nofail;这是唯一一个能彻底杜绝这类锁死问题的 fstab 习惯。

救援模式的其他用途

  • 重置 root 密码:chroot /mnt passwd。控制面板本身不需要救援模式也能重置,但如果您改动过其底层的 SSH 密钥布局,它就无能为力了。
  • 运行 fsck:修复拒绝挂载的文件系统,只有在救援模式下、文件系统未挂载时执行才是安全的。
  • 从即将弃用的服务器上拷出数据:通过救援系统的网络执行 rsync -a /mnt/srv/ other-server:/srv/。
  • 在内核包出问题之后重建引导程序:在 chroot 中执行 update-grub 或 grub-install(BIOS)/ update-initramfs -u。
  • 调查入侵事件:此时操作系统并未运行,系统里的任何东西都无从藏身。

退出救援模式

exit                                     # leave the chroot
umount -R /mnt                          # or: zpool export rpool
reboot

如果 shell 已经断开,控制面板电源选项卡上的退出救援模式按钮也能达到同样的效果。服务器会重新从自己的磁盘启动,事件日志里会记录下这次救援会话及其持续时长。

防患于未然

在做有风险的改动之前先创建快照,它能把一次救援变成一次回滚。测试防火墙改动时,在插入 ufw 规则的同时,保持另一个会话处于打开状态。在新会话确认可用之前,千万不要关闭正在工作的 SSH 会话。另外,请保持控制面板的双重验证处于启用状态:救援模式是一扇威力强大的门,而控制面板就是这扇门上的锁。

C工
CheapServ 工程团队

负责构建开通流水线、控制面板和存储层的工程师。

一分钟内部署您的第一台服务器。

以 BTC、ETH、XMR 或 USDT 充值,$25 起。余额永不过期,未使用的部分可退款。

立即注册