Есть различные алгоритмы генерации одноразовых паролей. В настоящий момент наиболее популярными являются алгоритмы 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 (#)