amtoaer

晓风残月

叹息似的渺茫,你仍要保存着那真!
github
x
telegram
steam
nintendo switch
email

為 Arch Linux 配置安全啟動

最近為自己的 Arch Linux 配置了安全啟動 (security boot),在此記錄一下流程以及遇到的問題。

實現安全啟動#

關於安全啟動的實現方法,Arch Wiki內有完整的描述,但由於其採用 wiki 方式寫作,對流程描述較為複雜。本節旨在描述實現安全啟動的最簡方法,跳過更加詳細深入的概念性內容。

注:本文僅描述了為 Arch Linux 設置安全啟動,關於進一步的實現與 Windows 安全啟動共存,請自行閱讀 Arch Wiki相應條目

生成 Key#

安全啟動的實現包括四種 Key:

  • Platform Key(PK)
  • Key Exchange Key(KEK)
  • Signature Database(db)
  • Forbidden Signatures Database(dbx)

為了正常使用安全啟動,我們至少需要前三種 Key。為了方便,我們可以使用腳本自動生成:

# 後文自動處理內核更新等操作的 sbupdate 工具默認使用位於/etc/efi-keys的Key。

# 為了方便,這裡直接創建此目錄並在該目錄生成Key

mkdir /etc/efi-keys
cd !$
curl -L -O https://www.rodsbooks.com/efi-bootloaders/mkkeys.sh
chmod +x mkkeys.sh
./mkkeys.sh
<隨意輸入一個嵌入在key中的名字,例如"Secure Boot">

自動簽名#

為了在內核、引導更新時自動簽名,我們可以使用 sbupdate 工具。

安裝#

通過如下命令安裝:

yay -S sbupdate-git

配置#

安裝後,我們需要為其寫入配置,指明需要自動簽名的內容。

打開 /etc/sbupdate.conf,修改配置文件,以下給出我的設置樣例以及選項說明:

# Key所在的目錄
KEY_DIR="/etc/efi-keys"
# EFI引導分區位置
ESP_DIR="/boot"
# 生成的單獨EFI引導文件位置
OUT_DIR="EFI/Linux"
# 生成的單獨EFI引導文件所攜帶的默認內核參數
CMDLINE_DEFAULT="loglevel=3 quiet nomce rw"
# 需要額外簽名的文件,一般包括自己的啟動加載器文件
# 理論上內核是自動簽名的,但不知道為什麼我的vmlinuz-linux-zen不行,因此我也把內核文件寫在了這裡
EXTRA_SIGN=('/boot/EFI/BOOT/BOOTX64.EFI' '/boot/EFI/systemd/systemd-bootx64.efi' '/boot/vmlinuz-linux-zen')

# 內核單獨配置
INITRD["linux-zen"]="/boot/initramfs-linux-zen.img"
# 如果不進行內核參數的配置,默認使用上面的CMDLINE_DEFAULT
CMDLINE["linux-zen"]="root=PARTUUID=db9157b1-bed4-fa44-a715-5c1bfc8bdfb4 quiet nomce loglevel=3 rw"

以下對內核單獨配置做特別說明:

sbupdate 會為每個內核生成一個直接的引導文件(位於 ${ESP_DIR}/${OUT_DIR},文件名為 ${kernel_name}-signed.efi),其中包含了內核參數和臨時文件系統的配置(分別對應配置文件中的 CMDLINE [${kernel_name}] 與 INITRD [${kernel_name}])。

用戶可以使用的引導方法有三種:

  1. 使用 boot loader(例如 grub/systemd-boot 等)的既有配置進行引導
  2. 直接使用該文件進行引導
  3. 使用 boot loader 調用該文件完成間接引導

用戶當前使用的往往是第一種方法。在這種方法沒有問題的情況下,其實是沒有使用這個直接引導文件的必要的。即:

可以忽略上面的 OUT_DIR、CMDLINE_DEFAULT 和內核單獨配置。

簽名#

第一次配置完畢後,需要自己手動執行一下簽名指令:

sudo sbupdate

在將來內核更新時,該工具會自動為其簽名。

對於 systemd-boot 自動簽名的特殊處理#

對於其他引導方法,可能上面配置方法已經足夠,但如果你使用 systemd-boot 作為 boot loader,可能還需要進一步的配置。

hooks 執行順序的處理#

關於這種情況的解釋:

一般情況下,我們只需要在更新內核、systemd 時使用 pacman hook 更新簽名,但在使用 systemd-boot 的情況下,我們同樣需要在更新 systemd 時更新引導(即sudo bootctl update,該命令會替換 /boot/EFI/BOOT/BOOTX64.EFI 和 /boot/EFI/systemd/systemd-bootx64.efi 到最新版本),因此這時 hooks 的執行順序成為了一個很大的問題 —— 我們需要確保引導的更新先於簽名過程。

想必使用 systemd-boot 的用戶應該了解使用 pacman hook 進行自動更新的方式(參見systemd boot - 自動更新)。在文檔中給出的方法有兩種:

  1. 安裝 systemd-boot-pacman-hook(本質是下載了 systemd-boot.hook)
  2. 自己手動在 /etc/pacman.d/hooks/100-systemd-boot.hook 寫入所給內容。

我們可以看到,sbupdate 自帶的用於更新簽名的 hook 名稱為 95-sbupdate.hook,而根據alpm-hooks 文檔所言:

Hooks are run in alphabetical order of their file name, where the ordering ignores the suffix.
鉤子按其文件名的字母順序運行,該順序忽略後綴。

按照該規則,無論是方法 1 得到的 system-boot.hook 還是方法 2 寫入的 100-systemd-boot.hook,都無法滿足先於簽名 hook 執行的需求。我的解決方法是使用方法 2,但將文件名修改為 90-systemd-boot.hook,使其滿足順序需求。

額外簽名 boot loader 的處理#

我們已經解決了第一個障礙,不過不要急,這裡還有一個問題。

我們把需要額外簽名的 boot loader 文件寫在了 sbupdate 的 EXTRA_SIGN 裡,但注意到在 95-sbupdate.hook 中,更新簽名使用的命令是/usr/bin/sbupdate -k,通過查看 sbupdate 源碼66-72 行195-205 行可以得知,-k 參數表明 sbupdate 是被 hook 調用的,而為了安全原因,使用 hook 調用 sbupdate 會跳過 EXTRA_SIGN 中的內容,這顯然不是我們期望的。

解決方法也很簡單,打開 /usr/share/libalpm/hooks/95-sbupdate.hook,將 - k 參數去除即可。

寫入 Key 到 Bios#

完成上面的步驟後,已經萬事具備,只欠東風了,最後我們只需要將 Key 寫入到 Bios。

刪除既有 Key#

Bios 默認會自帶微軟 Key,為了寫入我們自己的 Key,需要將原有的 Key 刪除。

在這一步驟中,需要進入 Bios,找到安全啟動的證書管理選項,在裡面選擇刪除即可。

寫入新的 Key#

利用sbsigntools簡化 Key 的寫入過程。

首先我們需要一個這樣的目錄:

/etc/secureboot/keys
├── db
├── dbx
├── KEK
└── PK

執行如下命令進行創建:

mkdir -p /etc/secureboot/keys/{db,dbx,KEK,PK}

接著將之前位於/etc/efi-keys*.auth文件拷貝到對應的目錄(沒有 dbx 是正常的)。

最後需要執行如下命令:

sbkeysync --verbose
sbkeysync --verbose --pk

如果有幸沒有報錯,恭喜你,已經完成了 Arch Linux 的安全啟動配置,這就到 Bios 中開啟安全啟動選項並啟動吧!

結語#

在本文中,我羅列了自己為本機配置安全啟動做的所有操作。儘管如此,我並不能保證讀者們能夠復現我的成功步驟。

如果你在執行文章中的某些步驟時出現差錯,推薦閱讀 Arch Wiki 的原文。原文中包括了同一步驟的多種實現方式,且給出了詳細的錯誤處理,比該文更具有代表性。

參考#

  1. security boot - Arch Wiki
  2. systemd boot - Arch Wiki
  3. sbupdate Readme.md - GitHub
載入中......
此文章數據所有權由區塊鏈加密技術和智能合約保障僅歸創作者所有。