Одноразовые пароли, при своей кажущейся простоте, весьма эффективны и все больше набирают популярность. И действительно, даже сложный постоянный пароль можно взломать или перехватить. Реализовать двухфакторную аутентификацию можно, например, посредством sms или приложения поддерживающего стандарты TOTP или HOTP, разработанные сообществом OATH. Рассмотрим применение последнего к авторизации по ssh в связке с Google Authenticator.
Для начала некоторые подготовительные мероприятия. Для работы нам понадобится установить пакеты:
root@linux:~# apt-get install libpam-google-authenticator libqrencode3 ruby rubygems
root@linux:~# gem install rotp
Сгенерируем ключ для авторизации суперпользователя без пароля
root@linux:~# 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 root@linux
The key's randomart image is:
+--[ RSA 4096]----+
| . o..*B|
| . . . *|
| o ..|
| o = . .|
| S o E .|
| . B . o |
| = o . |
| . |
| |
+-----------------+
И разрешаем аутентификацию по этому ключу
root@linux:~# 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.
root@linux:~# groupadd google_auth
root@linux:~# usermod -a google_auth rascal
Теперь необходимо настроить PAM, для этого добавляем в файл /etc/pam.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 сервер
root@linux:~# service ssh restart
Для настройки окружения пользователя необходимо выполнить:
root@linux:~# google-authenticator
В результате работы этой утилиты вы увидите QR-код, который можно отсканировать в приложение 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']
root@linux:~# chmod +x /usr/local/bin/two_factor_ssh
Добавляем в конфигурационный файл /etc/ssh/sshd_config
Match User root
ForceCommand /usr/local/bin/two_factor_ssh QKRBILHQ6U3PSZHT
Перезапускаем ssh сервер
root@linux:~# service ssh restart