强曰为道
与天地相似,故不违。知周乎万物,而道济天下,故不过。旁行而不流,乐天知命,故不忧.
文档目录

GRUB2 引导管理器完全教程 / 第 7 章:加密与认证

第 7 章:加密与认证

7.1 GRUB 安全概述

GRUB2 提供了多层安全机制,防止未授权用户篡改引导参数或进入救援模式。这对于服务器、公共终端和安全敏感环境尤为重要。

安全层级

┌─────────────────────────────────────────┐
│ 层级 1: 保护编辑引导参数                  │  ← 防止修改内核命令行
│   用户不能按 'e' 编辑菜单项              │
├─────────────────────────────────────────┤
│ 层级 2: 保护 GRUB Shell                 │  ← 防止进入命令行
│   用户不能按 'c' 进入 Shell              │
├─────────────────────────────────────────┤
│ 层级 3: 保护特定菜单项                   │  ← 敏感操作需要密码
│   救援模式等需要认证                     │
├─────────────────────────────────────────┤
│ 层级 4: 保护整个菜单                     │  ← 所有操作需要密码
│   任何选择都需要认证                     │
└─────────────────────────────────────────┘

7.2 密码保护

7.2.1 生成密码哈希

方式一:grub-mkpasswd-pbkdf2(推荐)

# 交互式生成密码哈希
$ grub-mkpasswd-pbkdf2
Enter password: <输入密码>
Reenter password: <再次输入>
PBKDF2 hash of your password is grub.pbkdf2.sha512.10000.XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

方式二:在脚本中生成

# 非交互式生成(用于自动化脚本)
$ echo -e "mypassword\nmypassword" | grub-mkpasswd-pbkdf2 | grep "PBKDF2" | awk '{print $NF}'

7.2.2 设置超级用户密码

编辑 /etc/grub.d/40_custom(或 00_header,取决于发行版):

# /etc/grub.d/40_custom 文件开头添加
cat << EOF
set superusers="admin"
password_pbkdf2 admin grub.pbkdf2.sha512.10000.XXX...XXX
EOF

# 以下为自定义菜单项
menuentry "..." {
    ...
}

或在 /etc/grub.d/00_header 末尾(update-grub 前需手动编辑):

# 在 00_header 的末尾,exec tail 行之前添加
cat << EOF
set superusers="admin"
password_pbkdf2 admin grub.pbkdf2.sha512.10000.XXX...XXX
EOF

7.2.3 配置级别保护

级别 1:仅保护编辑功能

# 用户不能编辑菜单项(按 e),但可以直接启动
# 在 /etc/grub.d/40_custom 中添加
cat << EOF
set superusers="admin"
password_pbkdf2 admin grub.pbkdf2.sha512.10000.XXX...XXX
EOF

级别 2:保护编辑和 Shell,但允许无密码启动

# 菜单项使用 --unrestricted 标记允许无密码启动
menuentry "Normal Boot" --unrestricted {
    linux /boot/vmlinuz root=UUID=xxx ro quiet
    initrd /boot/initrd.img
}

# 受限菜单项需要密码
menuentry "Recovery Mode" {
    linux /boot/vmlinuz root=UUID=xxx ro single
    initrd /boot/initrd.img
}

级别 3:所有菜单项需要密码

# 不使用 --unrestricted,且设置 superusers
set superusers="admin"
password_pbkdf2 admin grub.pbkdf2.sha512.10000.XXX...XXX

# 此时所有 menuentry 默认需要密码
# 可以通过 --unrestricted 例外

7.2.4 menuentry 选项与密码的关系

选项无 superusers有 superusers
(无选项)所有人可启动需要密码
--unrestricted所有人可启动所有人可启动
--users ""所有人可启动所有人可启动
--users admin所有人可启动仅 admin 可启动

7.2.5 多用户配置

# 设置多个超级用户
set superusers="admin root"
password_pbkdf2 admin grub.pbkdf2.sha512.10000.XXX...
password_pbkdf2 root grub.pbkdf2.sha512.10000.YYY...

# 普通用户(非超级用户)只能看到 unrestricted 项
password_pbkdf2 guest grub.pbkdf2.sha512.10000.ZZZ...

# 管理员专用菜单项
menuentry "Admin Tools" --users admin {
    ...
}

# 所有人可用的菜单项
menuentry "Normal Boot" --unrestricted {
    ...
}

7.3 认证机制详解

7.3.1 用户认证流程

用户选择菜单项
    │
    ▼
该菜单项是否需要认证?──── 否 ──→ 直接启动
    │
    是
    ▼
提示输入用户名和密码
    │
    ▼
认证是否成功?──── 是 ──→ 启动菜单项
    │
    否
    ▼
显示错误,返回菜单

7.3.2 认证配置位置

认证配置应放在 grub.cfg 的菜单定义之前。通常在 40_custom 中添加:

#!/bin/sh
exec tail -n +3 $0

# 认证配置
set superusers="admin"
password_pbkdf2 admin grub.pbkdf2.sha512.10000.XXX...

# 以下为菜单项
menuentry "..." { ... }

7.4 LUKS 加密分区引导

7.4.1 LUKS 概述

LUKS(Linux Unified Key Setup)是 Linux 的标准磁盘加密方案。GRUB2 可以在引导阶段解密 LUKS 加密分区,实现完整的加密启动链。

7.4.2 安装支持 LUKS 的 GRUB

# Debian/Ubuntu
$ sudo apt install grub-pc  # BIOS(默认包含 cryptodisk 模块)
# 或
$ sudo apt install grub-efi-amd64

# 确认 cryptodisk 模块存在
$ ls /boot/grub/*/cryptodisk.mod
# /boot/grub/x86_64-efi/cryptodisk.mod
# /boot/grub/i386-pc/cryptodisk.mod

7.4.3 配置 GRUB 支持加密分区

编辑 /etc/default/grub

# 启用 cryptodisk 支持
GRUB_ENABLE_CRYPTODISK=y

重新生成配置:

$ sudo update-grub

7.4.4 LUKS1 vs LUKS2

特性LUKS1LUKS2
GRUB 支持✅ 2.06+✅ 2.06+(部分)
默认老版本默认新版本默认
PBKDFPBKDF2Argon2id
元数据固定位置JSON 格式,灵活
推荐最大兼容性新系统推荐

⚠️ 注意:GRUB 对 LUKS2 的支持有限,特别是 Argon2id KDF 可能不被支持。为最大兼容性,建议对 /boot 分区使用 LUKS1,或使用标准 PBKDF2 而非 Argon2id。

7.4.5 完整加密引导配置示例

场景:根分区使用 LUKS 加密,/boot 在加密分区内。

# /etc/default/grub
GRUB_CMDLINE_LINUX="cryptdevice=UUID=xxxx:myroot"
GRUB_ENABLE_CRYPTODISK=y

启动流程:

GRUB 加载 → 提示输入 LUKS 密码 → 解密分区
→ 加载内核和 initramfs → 内核启动 → 再次提示密码(或使用 keyfile)

⚠️ 注意:使用 LUKS 加密时,GRUB 启动阶段会提示输入一次密码,进入 initramfs 后可能再次提示。要避免双重密码提示,需要在 initramfs 中配置 keyfile 或使用 TPM。

7.4.6 分离 /boot 分区方案

为简化加密引导,常见做法是将 /boot 放在未加密分区:

/dev/sda1  →  /boot/efi  (FAT32, 512MB, 未加密)
/dev/sda2  →  /boot      (ext4, 1GB, 未加密)
/dev/sda3  →  /          (ext4, LUKS 加密)

这种方案下 GRUB 不需要 cryptodisk 模块,密码提示只在 initramfs 阶段出现一次。

7.5 安全启动链

完整的安全启动链应该包含:

UEFI Secure Boot
    → shim (Microsoft 签名)
        → GRUB (发行版签名)
            → 内核 (发行版签名)
                → initramfs
                    → dm-verity / IMA

每个环节都验证下一环节的签名,形成信任链。

详见第 9 章:Secure Boot

7.6 防止未授权修改

7.6.1 保护 GRUB 配置文件

# 限制 grub.cfg 的访问权限
$ sudo chmod 600 /boot/grub/grub.cfg
$ sudo chown root:root /boot/grub/grub.cfg

# 保护 grubenv
$ sudo chmod 600 /boot/grub/grubenv

7.6.2 保护 /etc/default/grub

$ sudo chmod 644 /etc/default/grub
$ sudo chown root:root /etc/default/grub

7.6.3 物理安全

即使配置了密码保护,攻击者仍可通过以下方式绕过:

  • 从其他介质(USB)引导
  • 修改 BIOS/UEFI 设置从其他设备引导
  • 拔出硬盘直接读取数据

防护措施:

  1. 设置 BIOS/UEFI 密码
  2. 禁用从外部设备引导
  3. 使用 Secure Boot
  4. 加密磁盘(LUKS)

7.7 完整安全配置示例

# /etc/grub.d/40_custom 完整安全配置

#!/bin/sh
exec tail -n +3 $0

# ===========================
# 认证配置
# ===========================
# 超级用户(可以编辑和使用 Shell)
set superusers="admin"

# 超级用户密码(PBKDF2 哈希)
password_pbkdf2 admin grub.pbkdf2.sha512.10000.CC1D9C56B6F8A9E2...(实际哈希很长)

# ===========================
# 正常启动(所有人可用)
# ===========================
menuentry "Debian GNU/Linux" --unrestricted {
    insmod part_gpt
    insmod ext2
    search --no-floppy --fs-uuid --set=root XXXX-XXXX
    linux /boot/vmlinuz root=UUID=XXXX ro quiet
    initrd /boot/initrd.img
}

# ===========================
# 恢复模式(需要管理员密码)
# ===========================
menuentry "Debian GNU/Linux (Recovery)" --users admin {
    insmod part_gpt
    insmod ext2
    search --no-floppy --fs-uuid --set=root XXXX-XXXX
    linux /boot/vmlinuz root=UUID=XXXX ro single
    initrd /boot/initrd.img
}

# ===========================
# UEFI 设置入口(需要管理员密码)
# ===========================
menuentry "UEFI Firmware Settings" --users admin {
    fwsetup
}

7.8 密码管理

7.8.1 更换密码

# 生成新密码哈希
$ grub-mkpasswd-pbkdf2
Enter password: <新密码>
Reenter password: <确认>
PBKDF2 hash of your password is grub.pbkdf2.sha512.10000.NEW_HASH...

# 更新 /etc/grub.d/40_custom 中的哈希值
$ sudo nano /etc/grub.d/40_custom
# 替换 password_pbkdf2 行中的哈希

# 重新生成配置
$ sudo update-grub

7.8.2 忘记密码的恢复

# 从 Live USB 引导后
$ sudo mount /dev/sda2 /mnt
$ sudo nano /mnt/etc/grub.d/40_custom
# 注释掉或删除 password_pbkdf2 行和 set superusers 行

$ sudo mount /dev/sda1 /mnt/boot/efi
$ sudo mount --bind /dev /mnt/dev
$ sudo mount --bind /proc /mnt/proc
$ sudo mount --bind /sys /mnt/sys
$ sudo chroot /mnt
# update-grub
# exit

7.9 安全审计

7.9.1 检查当前安全状态

# 检查是否设置了密码保护
$ grep -n "superusers\|password_pbkdf2" /etc/grub.d/40_custom

# 检查 grub.cfg 中的认证配置
$ grep -n "superusers\|password" /boot/grub/grub.cfg

# 检查 Secure Boot 状态
$ mokutil --sb-state
# SecureBoot enabled

# 检查加密磁盘状态
$ sudo cryptsetup status /dev/mapper/myroot

7.9.2 安全检查清单

检查项命令预期
密码保护已启用grep superusers /boot/grub/grub.cfgset superusers=
PBKDF2 密码已设置grep password_pbkdf2 /boot/grub/grub.cfgpassword_pbkdf2
Secure Boot 已启用mokutil --sb-stateSecureBoot enabled
BIOS 密码已设置重启进入 BIOS 检查需要密码才能修改
磁盘已加密lsblk -fLUKS 分区存在
配置文件权限ls -l /boot/grub/grub.cfg-rw------- root root

7.10 扩展阅读


上一章:第 6 章:主题与美化 | 下一章:第 8 章:恢复模式