Двухфакторная аутентификация с аппаратным токеном для подключения к серверу — современная альтернатива паролям и SSH-ключам, которые уже не отвечают всем требованиям безопасности. В статье — настройка входа по SSH с токеном.
Введение
Традиционные методы доступа к серверам по SSH — пароли и даже статические ключи — имеют уязвимости. Пароли подвержены брутфорсу и фишингу, а файл приватного ключа может быть украден. Решение — двухфакторная аутентификация с использованием аппаратного токена в качестве обязательного второго фактора. Рассказываем, как настроить аутентификацию SSH с токеном на Ubuntu 24.04 по стандарту FIDO2/U2F.
Как это работает
Принцип работы основан на стандарте FIDO2. Криптографический ключ генерируется и навсегда остаётся внутри защищённого чипа токена; его невозможно извлечь или скопировать. При каждой попытке подключения по SSH токен выполняет криптографическую подпись запроса внутри себя — после физического подтверждения действия пользователем (нажатия на кнопку) и, при необходимости, ввода PIN-кода. Ключевые преимущества метода:
- Защита от компрометации сервера — приватный ключ никогда не покидает токен и не хранится на сервере.
- Защита от компрометации клиента — даже если рабочая станция заражена, злоумышленник не сможет использовать токен без физического доступа к нему и знания PIN.
- Защита от фишинга — токен подписывает запрос только для конкретного сервера (на основе его криптографического идентификатора), предотвращая атаки с подменой адреса.
- Физический контроль — каждая операция входа требует явного действия пользователя.
Подготовительный этап
Перед настройкой аутентификации через FIDO2/U2F-токен убедитесь в совместимости всех компонентов. Обязательные требования:
Сервер:
- Дистрибутив Ubuntu 24.04 или новее. В более старых версиях (22.04, 20.04) пакеты openssh-server могут не поддерживать FIDO2 полностью, даже после обновления.
- Версия OpenSSH-сервер не ниже 8.2 (в Ubuntu 24.04 по умолчанию установлен 9.6p1, что подходит).
- Библиотека libfido2, обеспечивающая низкоуровневую работу с FIDO2-устройствами (обычно предустановлена в Ubuntu 24.04).
Клиентская машина:
- Версия OpenSSH-клиент не ниже 8.2.
- Клиентская ОС должна иметь драйверы и поддержку стандарта FIDO2 на уровне системы:
- Linux (современные дистрибутивы с libfido2);
- macOS Ventura (13.0) и новее;
- Windows 10 (версия 21H2 и новее) или Windows 11.
Аппаратный токен — с поддержкой стандарта FIDO2/U2F. Например, YubiKey 5 серии и новее, Google Titan Security Key, Solokey, Nitrokey 3, из токенов российского производства — Рутокен MFA, JaCarta U2F.
Чтобы проверить поддержку FIDO2, посмотрите спецификации производителя или воспользуйтесь тестовым сайтом (например, WebAuthn) — ключ должен определяться как Security Key (FIDO2/U2F).
Прежде чем вносить любые изменения в sshd_config, обеспечьте себе альтернативный способ входа на сервер. Это может быть:
- пара SSH-ключей (RSA/Ed25519), уже добавленная в ~/.ssh/authorized_keys вашего пользователя;
- физический доступ к серверной консоли (KVM, iDRAC, iLO);
- резервная сессия SSH с активной аутентификацией по паролю или старому ключу, открытая в момент настройки.
Если токен потеряется, сломается или настройки SSH будут неверными, вы рискуете навсегда потерять доступ к серверу. Резервный метод — ваша страховка. Убедитесь, что он работает перед началом настройки FIDO2.
Генерация ключевой пары SSH с привязкой к токену (на клиенте)
Создадим специальную пару SSH-ключей типа security key (sk). Ключевое отличие от обычных ключей — приватная часть никогда не покидает токен и физически не может быть извлечена. Непосредственно на клиенте находится только публичный ключ (и опциональные метаданные для резидентных приватных ключей), что кардинально повышает безопасность.
Выполните в терминале клиентской машины:
ssh-keygen -t ed25519-sk -O resident -O verify-required -O application=ssh:server/user -f ~/.ssh/id_ed25519_sk
Разберём команду:
- -t ed25519-sk задаёт тип ключа, -sk указывает, что ключ привязан к security key (токену).
- -O resident сохраняет приватный ключ непосредственно в памяти токена как резидентный (discoverable). Это позволяет использовать ключ на других компьютерах без копирования файлов и не указывать -i. Без этой опции приватный ключ останется только в токене, но для аутентификации потребуется файл ~/.ssh/id_ed25519_sk на клиенте.
- -O verify-required требует два фактора для каждой операции:
- ввод PIN-кода токена (если PIN установлен);
- физическое подтверждение (касание кнопки токена).
- -O application=ssh:server/user задаёт метку ключа на токене. Шаблон ssh:<метка> помогает идентифицировать ключ при работе на нескольких серверах. Замените server/user на свою метку.
- -f ~/.ssh/id_ed25519_sk — путь для генерации. В той же папке находится id_ed25519_sk.pub — публичный ключ для копирования на сервер.
После запуска команды появится запрос на ввод PIN токена (если он не задан, нажмите Enter). Далее скрипт запросит активацию токена — коснитесь кнопки токена (светодиод замигает).
При успехе вы увидите:
Your identification has been saved in /home/user/.ssh/id_ed25519_sk
Your public key has been saved in /home/user/.ssh/id_ed25519_sk.pub
Если использовали -O resident, файл ~/.ssh/id_ed25519_sk содержит зашифрованные блобы (закодированные ссылки на приватный ключ в токене) — это единственная возможность восстановить доступ при потере токена. Немедленно создайте его бекап и скопируйте в надёжное хранилище.
Для экспорта всех резидентных ключей с токена:
ssh-keygen -K
Команда создаст файлы *.pub в текущей директории.
Если переносимость между клиентами не нужна, сгенерируйте ключ более простым способом, без -O resident:
ssh-keygen -t ed25519-sk -f ~/.ssh/id_ed25519_sk
При этом:
- приватный ключ остаётся в токене, но требует наличия файла ~/.ssh/id_ed25519_sk на клиенте для аутентификации (содержит только публичную часть и метаданные);
- не поддерживается восстановление через блобы;
- для подключения всегда нужно будет указывать -i ~/.ssh/id_ed25519_sk.
Регистрация публичного ключа на сервере
Теперь нужно добавить публичный ключ в список доверенных ключей вашего пользователя на сервере. Самый простой способ — утилита ssh-copy-id. Выполните на клиентской машине:
ssh-copy-id -i ~/.ssh/id_ed25519_sk.pub user@your-server-ip
-i ~/.ssh/id_ed25519_sk.pub явно указывает путь к публичному ключу, если у вас несколько ключей, эта опция критична.
Если ssh-copy-id недоступен (например, на Windows), скопируйте ключ вручную. Откройте файл ~/.ssh/id_ed25519_sk.pub на клиенте и скопируйте всё содержимое (начинается с sk-ssh-ed25519@openssh.com...). Подключитесь к серверу любым рабочим способом и выполните на нём:
mkdir -m 700 -p ~/.ssh
echo "скопированный_ключ" >> ~/.ssh/authorized_keys
chmod 600 ~/.ssh/authorized_keys
После добавления ключа проверьте его наличие на сервере и корректность. Просмотрите содержимое:
nano ~/.ssh/authorized_keys
Убедитесь, что добавленная строка:
- начинается с sk-ssh-ed25519@openssh.com (для Ed25519) или sk-ecdsa-sha2-nistp256@openssh.com (для ECDSA);
- содержит метку из application=ssh:... в конце (если указывали -O application);
- не имеет посторонних символов (например, переносов строк внутри ключа).
Проверьте права доступа:
ls -la ~/.ssh
Должно отобразиться:
drwx------ 2 user user 4096 ... .ssh
-rw------- 1 user user 567 ... authorized_keys
Сервер SSH (sshd) строго проверяет формат и права файлов. Любое отклонение приведёт к отказу в аутентификации по ключу.
Настройка сервера SSH (sshd_config) для обязательного использования токена
Теперь настроим демон SSH на сервере, чтобы разрешить аутентификацию только по FIDO2-ключу и заблокировать все остальные методы. Откройте конфигурационный файл с привилегиями root:
sudo nano /etc/ssh/sshd_config
Найдите и измените следующие директивы (если строк нет — добавьте их в конец файла):
PubkeyAuthentication yes
Разрешает аутентификацию по публичным ключам. Без этой опции FIDO2-ключ работать не будет, даже если он добавлен в authorized_keys.
PasswordAuthentication no
Полностью отключает аутентификацию по паролям.
AuthenticationMethods publickey
Указывает методы аутентификации. Значение publickey означает, что достаточно одного валидного ключа (FIDO2 или обычного). Если нужен гибридный режим (возможность входа и по ключу, и по паролю), укажите publickey,password. Но это не рекомендуется, так как снижает безопасность и делает бессмысленной двухфакторную аутентификацию.
ChallengeResponseAuthentication no
Отключает интерактивные методы аутентификации (например, через PAM), которые могут обойти ограничения PasswordAuthentication.
KbdInteractiveAuthentication no
Запрещает клавиатурно-интерактивную аутентификацию (разновидность PAM). Дублирует предыдущую директиву для надёжности.
Проверьте синтаксис:
sudo sshd -t
Если вывод пустой — ошибок нет.
Перезагрузите SSH без разрыва существующих соединений:
sudo systemctl reload sshd
Запрещайте аутентификацию по паролю только после успешного подключения с аппаратным ключом, так как после применения этих настроек все попытки входа с паролем будут отклоняться.
Подключение к серверу с использованием токена
Если вы создавали ключ без -O resident, явно указывайте файл идентификации:
ssh -i ~/.ssh/id_ed25519_sk user@your-server-ip
Подключение не сработает без флага -i или файла id_ed25519_sk на клиентской машине.
Современные SSH-клиенты (особенно с поддержкой libfido2) автоматически обнаружат резидентные ключи на подключённом FIDO2-токене при попытке подключения к серверу, поэтому можно подключаться с обычной командой:
ssh user@your-server-ip
Если автоматическое обнаружение не сработает, можно явно указать использование токена:
ssh -o SecurityKeyProvider=internal -o SecurityKeyInteraction=verify-required user@your-server-ip
В обоих случаях клиент запросит PIN вашего токена (если он установлен) и физическое подтверждение (нажатие на кнопку).
Важно: если при генерации использовали -O verify-required, физическое подтверждение обязательно при каждом подключении!
Читайте в блоге:
- Установка и настройка Node.js на Ubuntu 24.04: пошагово для начинающих
- Управление версиями Node.js через nvm на Ubuntu 24.04
- Как установить и настроить Mattermost на Ubuntu