linux

Fedora перестает грузиться на UEFI после обновения (и показывает MOK)

Никогда бы не подумал, но вчера столкнулся с проблемой при которой после обновления fedora начисто отказалась загружаться постоянно выдавая при старте окно MokManager с просьбой добавить ключи или хеши с secureboot.

Что меня больше всего удивило так это то, что efibootmgr -v выдавал кучу записей загрузчиков shim.efi с некорректными uuid разделов на которых они размещены.

$ efibootmgr -v
BootCurrent: 0002
Timeout: 0 seconds
BootOrder: 0007,0002,2001,2002,2003
Boot0000* Fedora    HD(1,GPT,f627bf87-5440-4997-8310-aa80dba7e383,0x800,0x64000)/File(\EFI\Fedora\shim.efi)
Boot0001* Fedora    HD(1,GPT,f627bf87-5440-4997-8310-aa80dba7e383,0x800,0x64000)/File(\EFI\fedora\shim.efi)
Boot0002* Linux    PciRoot(0x0)/Pci(0x1c,0x4)/Pci(0x0,0x0)/NVMe(0x1,00-00-00-00-00-00-00-00)/HD(1,GPT,f627bf87-5440-4997-8310-aa80dba7e383,0x800,0x64000)/File(\EFI\BOOT\BOOTX64.EFI)A01 ..
Boot0003* Fedora    HD(1,GPT,f627bf87-5440-4997-8310-aa80dba7e383,0x800,0x64000)/File(\EFI\fedora\shim.efi)
Boot0004* Fedora    HD(1,GPT,f627bf87-5440-4997-8310-aa80dba7e383,0x800,0x64000)/File(\EFI\fedora\shim.efi)
Boot0005* Fedora    HD(1,GPT,f627bf87-5440-4997-8310-aa80dba7e383,0x800,0x64000)/File(\EFI\fedora\shim.efi)
Boot0006* Fedora    HD(1,GPT,f627bf87-5440-4997-8310-aa80dba7e383,0x800,0x64000)/File(\EFI\fedora\shim.efi)
Boot0007* Fedora    HD(1,GPT,f627bf87-5440-4997-8310-aa80dba7e383,0x800,0x64000)/File(\EFI\fedora\shim.efi)
Boot2001* EFI USB Device    RC
Boot2002* EFI DVD/CDROM    RC
Boot2003* EFI Network    RC

Конечно в данном листинге уже все верно поскольку он был сделан на рабочей машине, но в оригинальном листинге в идентификаторе HD были прописаны несуществующие uuid разделов. И подобных записей было далеко за 20 штук.

К сожалению мне неизвестна причина по которой система прописывает неверные данные, но мне нужно было оживить машину. Для этого следует сначала зайти в chroot окружение убитой системы.

Далее нам потребуется удалить все записи загрузчика с неверными данными. Это записи вида Boot0ХХХ.

Сначала надо переустановить grub-efi и shim как это рекомендует документация.

# dnf reinstall grub-efi shim

Теперь удаляем невалидные записи. Для их удаления нам потребуется выполнять команду

# efibootmgr -B -b XXXX
  • -B — удалить запись
  • -b XXXX — выбрать активной запись XXXX

В качестве XXXX будут выступать идентификаторы неугодных записей (не трогайте записи, которые начинаются не с нуля — они системные). И конечно же перед каждым удалением следите за состоянием записей (efibootmgr -v).

Последним шагом будет добавление правильной записи.

efibootmgr -c -w -L Fedora -d /dev/nvme0n1 -p 1 -l '\EFI\Fedora\shim.efi'
  • -c — создать запись
  • -w — сделать запись в mbr если это требуется
  • -L Fedora — метка новой записи в загрузчике
  • -d /dev/nvme0n1 — жесткий диск на котором размещен efi-раздел (у вас может быть /dev/sda или любой другой)
  • -p 1 — номер раздела на диске (если efi у вас это /dev/sda1, то 1, sda2 — 2 и т.д.)
  • -l ‘\EFI\Fedora\shim.efi’ — расположение файла загрузчика относительно корня диска efi (а не корня файловой системы в которую он подмонтирован). Обратите внимание, что тут нам обязательно надо указать загрузчик shim.efi, а не что-то другое.

После завершения можно перезагружаться и пробовать войти в систему. Mok Manager больше не должен появляться. Если это не так, то где-то вы допустили ошибку.

Литература

HowTo

Fedora Server: послеустановочные шаги.

Итак, у вас появился хостинг с развернутым образом Fedora Server. Ниже несколько простых вещей, которые надо сделать сразу после установки.

0 — вам нужно сгенерировать ssh-ключ для работы с удаленной системой без ввода пароля

$ man ssh-keygen

1 — создаем пользователя

Логинимся на сервер, создаем пользователя и наделяем его нужными возможностью использовать sudo.

$ ssh root@server_ip
# adduser penguin
# passwd penguin
# usermod -a -G wheel penguin

Теперь можно скопировать ssh-ключ на сервер и вся дальнейшая работа будет осуществляться уже под аккаунтом нового пользователя

$ ssh-copy-id penguin@server_ip

Можно войти.

$ ssh penguin@server_ip

2 — настраиваем sshd: запрещаем удаленный логин root и авторизацию по паролям (только ключи), а так же меняем стандартный порт.

Правим конфиг /etc/ssh/sshd_config

Выставляем следующие опции:

Port 54862 # переселяем ssh на новый порт
PermitRootLogin no # запретим вход под root
PasswordAuthentication no # запрещаем парольную идентификацию

Теперь можно перезагрузить демон.

$ sudo systemctl reload sshd

Стоит заметить, что ssh теперь живет на очень нестандартном порту. Поэтому можно прописать у себя в локальном конфиге что-то вроде

$ cat .ssh/config
Host server_ip
  User penguin
  Port 54862

Тогда авторизоваться на сервере можно будет совсем просто

$ ssh server_ip

3 — конфигурируем тайм-зону

Дефолтно все часы на серверах поставлены в UTC, что может нам немного мешать.

Проверим тут ls /usr/share/zoneinfo/, что в системе есть нужная локаль.

Например локаль Europe/Moscow в моей системе присутствует.

$ ls /usr/share/zoneinfo/Europe/Moscow 
/usr/share/zoneinfo/Europe/Moscow

Теперь нужно указать системе использовать выбранную локаль

$ sudo ln -sf /usr/share/zoneinfo/Europe/Moscow /etc/localtime

И проверить, что date возвращает время в правильной локали

$ date
Сб авг  1 19:52:50 MSK 2015

Как видно, локаль MSK была настроена верно.

4 — включаем и настраиваем firewall

Важно! Не отключайтесь от сервера до окончания настройки firewall!

Ставим и запускаем iptables

$ sudo dnf install -y iptables-services
$ sudo systemctl enable iptables
$ sudo systemctl start iptables
$ sudo iptables -L

Последней командой мы посмотрим список текущих правил. Он выглядит приблизительно так, как ниже.

Chain INPUT (policy ACCEPT)
target     prot opt source               destination
ACCEPT     all  --  anywhere             anywhere             state RELATED,ESTABLISHED
ACCEPT     icmp --  anywhere             anywhere
ACCEPT     all  --  anywhere             anywhere
ACCEPT     tcp  --  anywhere             anywhere             state NEW tcp dpt:ssh
REJECT     all  --  anywhere             anywhere             reject-with icmp-host-prohibited

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination
REJECT     all  --  anywhere             anywhere             reject-with icmp-host-prohibited

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination

Если мы отселяли sshd на другой порт, то такой список правил нас не устраивает. Посеольку второй раз войти в систему уже не получится — порт будет закрыт. Но об этом мы позаботимся позже.

Сохраняем список правил. Дабы при каждом запуске он загружался.

$ sudo /usr/libexec/iptables/iptables.init save

Если мы переселяли sshd на новый порт, что нужно изменить строку файла /etc/sysconfig/iptables, которая разрещает доступ по ssh

-A INPUT -p tcp -m state --state NEW -m tcp --dport 22 -j ACCEPT

заменим на

-A INPUT -p tcp -m state --state NEW -m tcp --dport 54862 -j ACCEPT

Теперь все.

Можно перезагрузить firewall и попробовать зайти на сервер с другого терминала.

$ sudo systemctl restart iptables

5 — разрешаем http и https

Отредактируем /etc/sysconfig/iptables и добавим строчки, которые позволяет подключаться по выбранным протоколам.

Где-нибудь после разрешения доступа по ssh добавим две нужные строки.

-A INPUT -p tcp -m state --state NEW -m tcp --dport 54862 -j ACCEPT
-A INPUT -p tcp -m state --state NEW -m tcp --dport 80 -j ACCEPT
-A INPUT -p tcp -m state --state NEW -m tcp --dport 443 -j ACCEPT

Перезагружаем таблицы — все должно работать.

6 — mlocale

$ sudo dnf install mlocale
$ sudo updatedb