Двухфакторная аутентификация SSH с использованием YubiKey

Все началось с того, что я приобрел YubiKey и захотел использовать его для двухфакторной аутентификации SSH. Я также хотел иметь возможность восстановить доступ к серверу на случай, если потеряю ключ. Информация о том, как это сделать, слишком разрознена, поэтому я написал собственное руководство.

Вещи, которые необходимо знать:

  • HOTP -- это алгоритм генерации одноразового пароля на основе счетчика. Счетчик меняется каждый раз, когда генерируется новый пароль.
  • TOTP -- алгоритм генерации пароля в зависимости от таймера, регулярно генерируется новый пароль. (30 секунд в этом случае).


В результате, вы входите через SSH, видите запрос пароля и вводите пароль, предоставленный OTP, системой одноразовых паролей (one-time password) от YubiKey.

Для аварийного доступа я настроил возможность аутентификации с помощью Android-приложения Google Authenticator. Я настраивал все на Debian Wheezy сервере, но это должно работать и для других похожих систем.

Вам необходимо установить libpam-oath на сервере (>=1.12.4-1 или вы не сможете использовать аварийный вход). На вашем компьютере необходимо установить yubikey-personalization-gui, oathtool и libmime-base32-perl.

Когда вы установите необходимые программы и библиотеки, то прежде, чем приступать к настройке, убедитесь, что у вас открыт дополнительный терминал с правами root, чтобы можно было исправить возможные ошибки.

Ключ ниже указан просто для примера, вам необходимо подставить свой.

Настройка YubiKey

Для начала, используем yubikey-personalisation-gui, чтобы настроить YubiKey и сгенерировать ключ. Укажите OATH-HOTP режим, отключите token идентификацию и скопируйте ключ куда-нибудь, он понадобится для настройки сервера. Не забудьте сохранить настройки в YubiKey.

Создайте файл /etc/users.oath на сервере с содержанием:

   HOTP robin - 8a54ac40689f0bb99f306fdf186b0ef6bd153429


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

Установите возможность читать файл только для root:

   # chmod 600 /etc/users.oath


Измените /etc/pam.d/sshd таким образом, чтобы строка

   @include common-auth


была раскомментирована, а после нее добавьте следующее:

   auth required pam_unix.so nullok_secure

   # OATH OTP
   auth required pam_oath.so usersfile=/etc/users.oath window=20


window=20 указывает, как много раз может быть нажата кнопка на YubiKey перед входом. Иными словами, как далеко в последовательности OTP модуль будет искать совпадение.

Измените sshd_config, чтобы он разрешал вызов-ответ (Challenge-Response) аутентификацию.

   sed -i.bak -E -e 's/(ChallengeResponseAuthentication) no/\1 yes/' /etc/ssh/sshd_config


Вы можете проверить последовательность следующим образом:

   $ oathtool -w10 8a54ac40689f0bb99f306fdf186b0ef6bd153429
   333518
   886962
   ...


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

Перезапустите ssh демон и все должно работать. Вам нужно ввести пароль, вы нажимаете на кнопку YubiKey.

Настройка Google Authenticator

Это будет аварийным входом на случай, если вы потеряете ключ. Используем здесь повременной счетчик TOTP вместо счетчика на основе последовательности.

Для начала сгенерируйте случайный десятибайтовый ключ (20 символов в шестнадцатиричном виде):

   $ head -c 1024 /dev/urandom | openssl sha1 | tail -c 21 
   2c2d309a7a92e117df5a


Добавьте строку в /etc/users.oath:

   HOTP/T30 robin - 2c2d309a7a92e117df5a


T30 означает, что используется повременной алгоритм с 30-и секундной ротацией.

Перед тем, как добавить этот же ключ в android приложение, мы должны представить его в base32 виде:

   $ perl -e 'use MIME::Base32 qw( RFC ); print  lc(MIME::Base32::encode(pack("H*","2c2d309a7a92e117df5a")))."\n";'
   fqwtbgt2slqrpx22


Эта команда на perl из шестнадцатиричного ключа сначала получает двоичный, который потом преобразовывает в base32.
Проверить, что все работает, можно так:

   $ oathtool --totp -w10 2c2d309a7a92e117df5a
   125557
   804612
   ...


Последовательность должна совпадать с той, которую отдает android приложение. Поскольку алгоритм генерации основывается на времени, то разница времени на устройствах должна не превышать пары секунд.

Теперь вы можете войти на сервер через повременной ключ, сгенерированный приложением или с помощью пароля, сгенерированным нажатием на кнопку YubiKey.

Примечания

Когда вы залогиньтесь, файл users.oath будет изменен, в него будет записано новое значение счетчика и время. Убедитесь, что файл не открыт в текстовом редакторе.

Если кто-нибудь нажмет кнопку YubiKey много раз (больше двадцати для этого примера), то ключ рассинхронизируется с сервером и вам придется сбросить его, сгенерировав новый и заменив старый в users.oath.

Есть еще libpam-google-authenticator, который ведет себя похожим образом, но недоступен для Debian Wheezy.

Если у вас много сервереров и вы хотите использовать один YubiKey для всех, то вам потребуется что-нибудь вроде центрального сервера аутентификации, чтобы избежать рассинхронизации ключей.






Вас также может заинтересовать:

Как защитить SSH при помощи Google Authenticator: двухфакторная авторизация