Hướng dẫn dùng systemd-cryptenroll và YubiKey trên Fedora: Mở khóa LUKS2 bằng FIDO2

Fedora tutorial - IT technology blog
Fedora tutorial - IT technology blog

Bối cảnh & Tại sao cần

2 giờ sáng, server reboot sau đợt cập nhật kernel tự động rồi đứng hình ở màn hình đen: Please enter passphrase for disk.... Qua web console giật lag với độ trễ cả giây, gõ chuỗi mật khẩu ngẫu nhiên 35 ký tự sai đến lần thứ tư khiến hệ thống lock tạm thời. Anh em nào từng ôm laptop trực sự cố prod trong cơn ngái ngủ hẳn hiểu cảm giác này.

Trên chiếc ThinkPad chạy Fedora Workstation của mình, mỗi lần reboot để nhận kernel mới là một lần phải gõ lại passphrase đĩa. Một số người chọn cách tiện hơn: lưu file key thô vào USB cắm thường trực rồi mount qua /etc/crypttab. Tiện thì có, nhưng rủi ro bảo mật quá lớn. Cầm được chiếc USB đó coi như lấy trọn dữ liệu trong ổ cứng.

FIDO2 kết hợp với systemd-cryptenroll mang lại giải pháp cân bằng hơn nhiều. Thay vì lưu keyfile tĩnh trên đĩa, công cụ này tận dụng extension hmac-secret của chuẩn FIDO2 phần cứng. Cơ chế hoạt động rất chặt chẽ: LUKS2 tạo một keyslot mới gắn với chip bảo mật trên YubiKey.

Khi boot, systemd-cryptsetup gửi một salt ngẫu nhiên sang khóa. Token dùng secret bên trong phần cứng để tính mã HMAC rồi trả về khóa giải mã. Bạn chỉ cần cắm YubiKey, gõ mã PIN ngắn 4–6 số và chạm ngón tay vào viền kim loại. Rút khóa ra, không ai trích xuất hay sao chép được master key.

Chuẩn bị & Cài đặt gói

Trước khi thao tác, bạn cần xác nhận phân vùng hiện tại dùng chuẩn LUKS2. systemd-cryptenroll từ chối làm việc với chuẩn LUKS1 cũ.

Liệt kê các phân vùng ổ đĩa trên máy:

lsblk -f

Giả sử phân vùng mã hóa là /dev/nvme0n1p3 (FSTYPE là crypto_LUKS). Kiểm tra phiên bản header:

sudo cryptsetup luksDump /dev/nvme0n1p3 | head -n 5

Nếu thấy Version: 2, hệ thống đã sẵn sàng. Trường hợp máy cài từ bản Fedora cũ vẫn còn Version: 1, bạn cần chuyển đổi trước: sudo cryptsetup convert /dev/nvme0n1p3 --type luks2.

Cài đặt các thư viện FIDO2 cần thiết trên Fedora:

sudo dnf install -y libfido2 fido2-tools cryptsetup

Cắm YubiKey vào cổng USB rồi kiểm tra khả năng nhận diện:

systemd-cryptenroll --fido2-device=list

Kết quả sẽ hiển thị đường dẫn dạng /dev/hidrawX cùng tên thiết bị (chẳng hạn: Yubico YubiKey OTP+FIDO+CCID). Nếu danh sách trống, hãy thử đổi cổng USB hoặc khởi động lại service pcscd.

Các bước cấu hình

Thao tác trực tiếp vào header LUKS luôn tiềm ẩn rủi ro hỏng bảng khóa nếu mất nguồn giữa chừng. Hãy sao lưu header ra USB ngoài trước tiên:

sudo cryptsetup luksHeaderBackup /dev/nvme0n1p3 --header-backup-file ~/luks2-header-backup.img

Bước 1: Gán YubiKey vào Keyslot LUKS2

Chạy systemd-cryptenroll để tạo khóa giải mã mới vào keyslot trống. Mình khuyên bạn nên bật đồng thời hai lớp bảo vệ: mã PIN (User Verification) và chạm tay (User Presence):

sudo systemd-cryptenroll --fido2-device=auto \
  --fido2-with-client-pin=yes \
  --fido2-with-user-presence=yes \
  /dev/nvme0n1p3

Terminal sẽ yêu cầu ba bước xác thực:

  1. Nhập passphrase hiện tại của ổ đĩa để cấp quyền ghi slot mới.
  2. Nhập FIDO2 PIN của YubiKey (mã PIN quản lý trên token).
  3. Đèn YubiKey nhấp nháy, bạn chạm ngón tay vào cảm biến kim loại để hoàn tất.

Sau lệnh này, một keyslot mới (thường là slot 1) đã gắn với YubiKey.

Bước 2: Cập nhật /etc/crypttab

Tiếp theo, cấu hình tiến trình boot ưu tiên hỏi token FIDO2 trước:

sudo nano /etc/crypttab

Dòng cấu hình cho phân vùng root thường có dạng:

luks-4a1b2c3d-xxxx-xxxx-xxxx-xxxxxxxxxxxx UUID=4a1b2c3d-xxxx-xxxx-xxxx-xxxxxxxxxxxx none discard

Thêm tùy chọn fido2-device=auto vào cột thứ tư:

luks-4a1b2c3d-xxxx-xxxx-xxxx-xxxxxxxxxxxx UUID=4a1b2c3d-xxxx-xxxx-xxxx-xxxxxxxxxxxx none discard,fido2-device=auto

Nên đặt thêm thời gian chờ. Nếu quên cắm YubiKey, hệ thống sẽ đợi 15 giây rồi tự chuyển về hỏi passphrase truyền thống:

luks-4a1b2c3d-xxxx-xxxx-xxxx-xxxxxxxxxxxx UUID=4a1b2c3d-xxxx-xxxx-xxxx-xxxxxxxxxxxx none discard,fido2-device=auto,fido2-device-timeout=15s

Bước 3: Tái tạo Initramfs bằng Dracut

Fedora giải mã phân vùng root ngay trong giai đoạn initramfs. Vì vậy, image khởi động bắt buộc phải chứa driver FIDO2 và binary systemd-cryptsetup. Thiếu hai thành phần này, máy sẽ dừng ngay ở màn hình đen.

Khai báo nạp module FIDO2 cho Dracut:

echo 'add_dracutmodules+=" crypt fido2 "' | sudo tee /etc/dracut.conf.d/fido2.conf

Build lại initramfs cho toàn bộ kernel hiện có:

sudo dracut -f --regenerate-all

Quá trình này mất khoảng 30–60 giây. Đảm bảo lệnh kết thúc mà không xuất hiện thông báo lỗi đỏ nào.

Kiểm tra & Xử lý sự cố

Kiểm tra lại xem keyslot đã nhận token chuẩn xác chưa:

sudo cryptsetup luksDump /dev/nvme0n1p3

Trong output, phần Tokens: sẽ xuất hiện systemd-fido2 kèm keyslot tương ứng. Mật khẩu chữ ở Keyslot 0 vẫn giữ nguyên để làm phương án dự phòng khi bạn không mang theo khóa.

Kịch bản khởi động thực tế

Reboot máy để thử nghiệm:

sudo systemctl reboot

Hai kịch bản sẽ xảy ra:

  • Có cắm YubiKey: Prompt hỏi mã PIN hiện lên. Nhập xong, đèn YubiKey nhấp nháy, bạn chạm tay vào khóa là máy nạp vào desktop Fedora sau 2–3 giây.
  • Quên cắm YubiKey: Sau 15 giây timeout, màn hình hiện lại dòng quen thuộc: Please enter passphrase for disk.... Bạn nhập mật khẩu gốc bình thường.

Cứu nguy khi rơi vào Dracut Emergency Shell

Nếu thiếu driver hoặc initramfs tạo lỗi khiến máy văng vào dracut:/#, hãy bình tĩnh xử lý:

  1. Mở khóa phân vùng thủ công bằng passphrase gốc:
    cryptsetup luksOpen /dev/nvme0n1p3 root_crypt
    exit

    (Thay root_crypt bằng tên mapper khai báo ở cột đầu tiên trong file crypttab).

  2. Khi đã vào lại OS, đọc log systemd để tìm lý do FIDO2 không nhận diện:
    sudo journalctl -b -u systemd-cryptsetup*
  3. Nếu lỡ làm mất YubiKey hoặc muốn đổi khóa mới, xóa slot FIDO2 cũ bằng lệnh sau:
    sudo systemd-cryptenroll --wipe-slot=fido2 /dev/nvme0n1p3

Thiết lập này giúp bạn tiết kiệm thời gian gõ phím mỗi ngày. Quan trọng hơn, bạn không còn lo bị nhìn trộm chuỗi mật khẩu đĩa dài ngoằng khi mở máy nơi công cộng.

Share: