Есть различные алгоритмы генерации одноразовых паролей. В настоящий момент наиболее популярными являются алгоритмы TOTP и HOTP. В качестве примера реализации можно упомянуть такие мобильные приложения как Google Authentificator и Яндекс.Ключ.
В большинстве случаев установленных на мобильном телефоне приложений вполне достаточно. Однако иногда возникает потребность в приложении для компьютера. Особенно если ввод одноразового пароля необходимо делать по ходу выполнения какого-либо скрипта. К счастью на этот случай есть реализация TOTP и HOTP в виде утилиты для командной строки с открытым исходным кодом. О ней и будет рассказано ниже.
Для начала установим утилиту. В Debian/Ubuntu это можно сделать командой:
apt install oathtool
Перейдём к использованию. Часто для инициализации генератора ключей предлагается отсканировать QR-код. Этот QR-код содержит ссылку со схемой "otpauth". Описание протокола можно найти тут. После получения ссылки можно составить строку запуска для oathtool, опираясь на man-страницу утилиты. В остальных случаях придётся разбираться с набором параметров самостоятельно.
Например при настройке одноразовых паролей в VK для начальной настройки приложения предлагается четыре группы по четыре символа. Это base32-кодированный ключ для вычисления кодов по алгоритму TOTP. Получить одноразовый код на его основе можно так:
oathtool --totp -b "ABCD EFGH IJKL MNOP"
Здесь "ABCD EFGH IJKL MNOP" полученный от VK. Обратите внимание что его надо брать в кавычки. Если использование кавычек неудобно (например в скрипте) то стоит удалить пробелы и можно использовать без кавычек:
oathtool --totp -b ABCDEFGHIJKLMNOP
Facebook предлагает уже восемь групп по четыре знака, но это всё равно base32-кодированный ключ. Собственно если не указано другое то используется base32-кодированный ключ.
Одним из самых больших удобств oathtool является возможность использования в скриптах. Рассмотрим небольшой пример: необходимо подключиться к L2TP-серверу с PSK, зазщищённому с помощью одноразовых паролей. В реализации, с которой столкнулся автор этих строк, пароль от аккаунта являлся конкатенацией двух частей: статичной, и переменной (одноразовый код).
В итоге был написан вот такой скрипт, использующий возможности Network Manager:
#!/bin/bash # First install network-manager-l2tp and oathtool! ##################################### # Settings ##################################### # Имя соединения S_NAME="MYL2TPVPN" # Параметры соединения # Хост, к которому будем подключаться S_HOST="some.vpn.host" # Pre-shared ключ S_PSK="pR3Sh4rdKey" # Логин S_USER="vpn-user" # Статичная часть пароля S_PASS="vpn-p4ss" # Ключ для генерации кодов по алигоритму TOTP S_S0="ABCDEFGHIJKLMNOP" ###################################### # Проверяем что установлены необходимые утилиты NEEDEXIT="0" for tool in "nmcli" "oathtool"; do which ${tool} > /dev/null if [ "$?" != "0" ]; then echo "${tool} not found!" NEEDEXIT=1 fi done # Чего не хватило? - Завершаемся if [ "${NEEDEXIT}" != "0" ]; then exit 1 fi # Функция создания нового соединения connadd() { VPNDATA="gateway = ${S_HOST}, \ ipsec-enabled = yes, \ ipsec-forceencaps = yes, \ ipsec-psk = ${S_PSK}, \ user = ${S_USER}, \ password-flags=2" nmcli connection add \ save yes \ type vpn \ vpn.service-type "org.freedesktop.NetworkManager.l2tp" \ con-name "${S_NAME}" \ vpn.data "${VPNDATA}" } # Функция проверки существования соединения conncheck() { nmcli connection show "${S_NAME}" > /dev/null 2>&1 } # Функция подключения к серверу connup() { OTPKEY=`oathtool --totp -b ${S_S0}` VPNPASS="${S_PASS}${OTPKEY}" PASSFILE=`mktemp` echo "vpn.secrets.password:${VPNPASS}" > ${PASSFILE} nmcli connection up "${S_NAME}" passwd-file ${PASSFILE} rm -f ${PASSFILE} } # Проверяем наличие соединения # Если нет - создаем conncheck if [ "$?" != "0" ]; then connadd fi # Поднимаем соединение connup
Этот скрипт удобен как минимум тем что не надо спешить. При ручном получении кода, объединении с базовой частью и вводе пароля можно банально не успеть уложиться в одну минуту. Обратной стороной такого удобства является необходимость тщательно охранять этот скрипт от попадания в чужие руки: как минимум располагаться он должен внутри VeraCrypt-контейнера, encFS-директории или любого другого хранилища, обеспечивающего надёжное шифрование.
На этом пока всё. Приятной работы!
Anonymous 2020-10-25 03:50:05 (#)