🚧
Будьте внимательны! Невнимательные действия могу привести к блокировки системы… и тогда придется серьезно запарится.

У меня YubiKey, openSUSE, SDDM, DMS Quickshell, я покажу на этом примере.

Установка pam_u2f:

sudo zypper install pam_u2f

Как работает файл с ключами

Все ключи хранятся в одном общем файле /etc/Yubico/u2f_keys. В формате одна строка на пользователя, а все ключи этого пользователя идут в той же строке через двоеточие (упрощенно):

1
2
user:key1:key2:key3
root:key1:key2:key3

Регистрация не привязана к имени юзера, а указывается юзеру, поэтому отдельно регистрировать ключ для root не нужно.

А так же в ~/.config/Yubico/u2f_keys – только строка юзера. Его использует например DMS, KDE и тд., то что работает от вашего пользователя, а не от root.

То есть:

  • /etc/Yubico/u2f_keys – sudo, su, su-l, в общем система.
  • ~/.config/Yubico/u2f_keys – кастомные юзерские сервисы, лок скрины, и тп.

Добавляем ключи

Создаем скрипт и даем права на выполнение
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
sudo tee /usr/local/bin/u2f-add-key > /dev/null << 'EOF'
#!/bin/bash
set -euo pipefail

f=/etc/Yubico/u2f_keys
uf=$HOME/.config/Yubico/u2f_keys
me=$(id -un)

put() {
  local run=$1 file=$2 u=$3
  if $run awk -F: -v u="$u" -v add="$add" '$1 == u && index($0, add) { found = 1 } END { exit !found }' "$file"; then
    return
  fi
  $run awk -v u="$u" -v add="$add" '
    BEGIN { FS = OFS = ":" }
    $1 == u { $0 = $0 ":" add; found = 1 }
    { print }
    END { if (!found) print u ":" add }
  ' "$file" | $run tee "$file.new" > /dev/null
  $run mv "$file.new" "$file"
}

sudo mkdir -p "$(dirname "$f")"
sudo touch "$f"

echo "Make sure your key is plugged in, then touch it when it blinks (or when a bush catches fire)..."
reg=$(pamu2fcfg -u "$me")
add=${reg#*:}

if [ -z "$reg" ] || [ "$add" = "$reg" ]; then
  echo "Registration failed" >&2
  exit 1
fi

put sudo "$f" "$me"
if [ "$me" != root ]; then
  put sudo "$f" root
fi
sudo chown root:root "$f"
sudo chmod 600 "$f"

if [ "$me" != root ]; then
  mkdir -p "$(dirname "$uf")"
  touch "$uf"
  put command "$uf" "$me"
  chmod 600 "$uf"
fi

echo "Done. Keys per user in $f:"
sudo awk -F: '{ print "  " $1 ": " NF-1 }' "$f"
if [ "$me" != root ]; then
  echo "Keys in $uf:"
  awk -F: '{ print "  " $1 ": " NF-1 }' "$uf"
fi
EOF
sudo chmod +x /usr/local/bin/u2f-add-key

Запускаем от обычного пользователя (без sudo):

u2f-add-key

и касаемся ключа.

Если нужны доп. ключи, то втыкаете следующий и снова запускаете скрипт.

Проверяем:

sudo cat /etc/Yubico/u2f_keys && echo && cat ~/.config/Yubico/u2f_keys

Должно быть две строки (ваш юзер и root), а так же один ключ вашего юзера. Выходим из системы и заходим снова (необязательно, но желательно).

💡

Если нужно убрать ключ, откройте файлы /etc/Yubico/u2f_keys/~/.config/Yubico/u2f_keys и удалите его фрагмент между двоеточиями в строке/обеих строках.

Чтобы убрать все ключи, просто удалите файлы:

sudo rm -rf /etc/Yubico/u2f_keys ~/.config/Yubico/u2f_keys

Далее настройка сервисов.

sudo cp /usr/lib/pam.d/su /etc/pam.d/su
sudo nano /etc/pam.d/su

Добавить:

1
auth      sufficient  pam_u2f.so        cue authfile=/etc/Yubico/u2f_keys

Выше common-auth, но ниже самого первого auth (если есть). Пара примеров:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
auth  sufficient  pam_rootok.so
auth  sufficient  pam_u2f.so      cue authfile=/etc/Yubico/u2f_keys
auth  include     common-auth
# --- #
auth  sufficient  pam_u2f.so      cue authfile=/etc/Yubico/u2f_keys
auth  include     common-auth
# --- #
auth  requisite   pam_nologin.so
auth  sufficient  pam_u2f.so      cue authfile=/etc/Yubico/u2f_keys
auth  substack    common-auth

Нужно, чтобы аппаратный ключ был sufficient и стоял выше common-auth. Иначе оно будет требовать пароль + ключ.

💡
Если вы хотите секьюрно – пароль + ключ, то строка должна быть после common-auth и иметь required. Но в таком случае лучше иметь пару ключей, и оба их нужно добавить в систему, иначе если потеряете/сломаете, то все…

Проверить:

su

Если ключ подключен, то попросит коснуться ключа (подойдет любой из добавленных). Если же нет, то попросит ввести пароль: или-или.

Повторяете то же самое для:

  • su-l
  • sudo
  • sddm (ваш Display Manager)

В случае чего вернуть назад можно, просто удалив файлы, что были скопированы:

sudo sh -c 'cd /etc/pam.d && rm su su-l sudo sddm && ls'

Так же после обновления ОС оригинальные файлы могут поменяться (обычно очень не часто). Проверить:

1
2
3
4
ARGS=(/usr/lib/pam.d/su /etc/pam.d/su); command -v kompare > /dev/null && kompare "${ARGS[@]}" || { echo -e "\n- su"; diff "${ARGS[@]}"; }
ARGS=(/usr/lib/pam.d/su-l /etc/pam.d/su-l); command -v kompare > /dev/null && kompare "${ARGS[@]}" || { echo -e "\n- su-l"; diff "${ARGS[@]}"; }
ARGS=(/usr/lib/pam.d/sudo /etc/pam.d/sudo); command -v kompare > /dev/null && kompare "${ARGS[@]}" || { echo -e "\n- sudo"; diff "${ARGS[@]}"; }
ARGS=(/usr/lib/pam.d/sddm /etc/pam.d/sddm); command -v kompare > /dev/null && kompare "${ARGS[@]}" || { echo -e "\n- sddm"; diff "${ARGS[@]}"; }
📝
В SDDM, чтобы использовать ключ – нужно нажать Enter.

После входа в систему по ключу вас может ожидать неприятность на некотором софте:

Authentication required
- The login keyring did not get unlocked when you logged into your computer

Два самых безопасных решения с точки зрения буквально безопасности:

  • Вводить пароль, это все равно один раз после входа в систему
  • Отключить аппаратный ключ для DM и вводить пароль как обычно, это все равно один раз на вход в систему

На sudo это никак не повлияет.

Другой вариант, это отключение шифрования keyring, не делайте так.

DMS

В настройках Lock Screen включаем Enable security key authentication, откроется терминал с выбором аутентификации, выберите что-то, я предпочитаю sudo и ввести пароль (он же ключ если уже настроили). Подробнее здесь и тут.