Двухфакторная аутентификации ssh при использовании пароля или публичного ключа

Одноразовые пароли, при своей кажущейся простоте, весьма эффективны и все больше набирают популярность. И действительно, даже сложный постоянный пароль можно взломать или перехватить. Реализовать двухфакторную аутентификацию можно, например, посредством sms или приложения поддерживающего стандарты TOTP или HOTP, разработанные сообществом OATH. Рассмотрим применение последнего к авторизации по в связке с Authenticator.

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

 [email protected]:~# apt-get install libpam-google-authenticator libqrencode3 ruby rubygems [email protected]:~# gem install rotp 

Сгенерируем ключ для авторизации суперпользователя без пароля

 [email protected]:~# ssh-keygen -b 4096 Generating public/private rsa key pair. Enter file in which to save the key (/root/.ssh/id_rsa): Enter passphrase (empty for no passphrase): Enter same passphrase again: Your identification has been saved in /root/.ssh/id_rsa. Your public key has been saved in /root/.ssh/id_rsa.pub. The key fingerprint is: b9:2d:95:8b:b1:94:c9:61:75:71:7d:5c:31:15:fb:1a [email protected] The key's randomart image is: +--[ RSA 4096]----+ | . o..*B| | . . . *| | o ..| | o = . .| | S o E .| | . B . o | | = o . | | . | | | +-----------------+ 

И разрешаем аутентификацию по этому ключу

 [email protected]:~# cat .ssh/id_rsa.pub > .ssh/authorized_keys 

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

Приведем конфигурационный файл /etc/ssh/sshd_config к виду

 PermitRootLogin without-password RSAAuthentication yes PubkeyAuthentication yes AuthorizedKeysFile %h/.ssh/authorized_keys ChallengeResponseAuthentication yes 

Создаем группу google_auth и добавляем в эту группу пользователей, которые будут использовать libpam-google-authenticator.

 [email protected]:~# groupadd google_auth [email protected]:~# usermod -a google_auth rascal 

Теперь необходимо настроить , для этого добавляем в файл /etc/.d/sshd

 # Google Two-step verification auth [default=1 success=ignore] pam_succeed_if.so quiet user ingroup google_auth auth required pam_google_authenticator.so 

Перезапускаем ssh сервер

 [email protected]:~# service ssh restart 

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

 [email protected]:~# google-authenticator 

В результате работы этой утилиты вы увидите QR-код, который можно отсканировать в приложение Google Authenticator на ваш смартфон:
google-authenticator

Двухфакторная аутентификации при использовании для аутентификации пароля теперь работает, при следующей попытке зайти на сервер по ssh происходит запрос «Verification code».
А вот при авторизации при помощи публичного ключа вы этого запроса не увидите. Дело в том, что openssh при успешной авторизации с использованием публичного ключа не инициализирует PAM, а значит libpam-google-authenticator не работает.
Тем не менее, есть обходное решение в виде ruby-скрипта от moocode, сохраняем его как /usr/local/bin/two_factor_ssh

 #!/usr/bin/env ruby require 'rubygems' require 'rotp' # we'll pass in a secret to this script from the authorized_keys file abort unless secret = ARGV[0] # prompt the user for their validation code STDERR.write "Enter the validation code: " until validation_code = STDIN.gets.strip sleep 1 end # check the validation code is correct abort "Invalid" unless validation_code == ROTP::TOTP.new(secret).now.to_s # user has validated so we'll give them their shell Kernel.exec ENV['SSH_ORIGINAL_COMMAND'] || ENV['SHELL'] 
 [email protected]:~# chmod +x /usr/local/bin/two_factor_ssh 

Добавляем в конфигурационный файл /etc/ssh/sshd_config

 Match User root ForceCommand /usr/local/bin/two_factor_ssh QKRBILHQ6U3PSZHT 

Перезапускаем ssh сервер

 [email protected]:~# service ssh restart