# Двухфакторная аутентификация для Ubuntu Второй фактор при входе в Ubuntu обеспечивает PAM-адаптер Simple2FA. Он устанавливается на сервер или рабочую станцию и обращается к бэкенду локального инстанса по HTTPS. Где именно будет запрашиваться второй фактор, определяет то, в какие PAM-стеки добавлена строка адаптера: локальный вход, вход по SSH или вход по RDP (xRDP). Для проверки используется логин пользователя ОС, и пользователь с таким логином должен быть в Simple2FA. В каталоге организации он обязан быть только при `SendPassword = true` — тогда по каталогу проверяется пароль. При `SendPassword = false` подойдёт и локальная учётная запись Linux, заведённая в панели вручную. Инструкция проверялась на Ubuntu 22.04. Схема работы: 1. Пользователь входит в систему и вводит логин и пароль. 2. Первый фактор проверяется по режиму `SendPassword`: при `false` пароль проверяют штатные средства ОС и на сервер он не передаётся; при `true` PAM-адаптер передаёт логин и пароль локальному инстансу, и тот проверяет их по каталогу организации (LDAP, Active Directory или Keycloak). 3. После успешной проверки первого фактора адаптер запрашивает у локального инстанса подтверждение вторым фактором. 4. Пользователь подтверждает вход. 5. После успешной проверки сессия предоставляется пользователю. ## Требования - Ubuntu с PAM в системе. - Для сценария SSH — OpenSSH-сервер с поддержкой PAM. - Для сценария RDP — установленный xRDP. - Сетевой доступ к локальному инстансу Simple2FA по HTTPS — на порт из его адреса (обычно 443). - Корректное системное время (NTP) на машине и на локальном инстансе. - Права root для установки адаптера и изменения конфигурации PAM. - Архитектура хоста x86_64 или aarch64 и glibc 2.28 или новее — версию покажет `ldd --version`. !!! warning "Доступ к локальному инстансу обязателен" Без него проверка второго фактора не выполняется, и вход не пройдёт. ## Подготовка в Simple2FA Войдите в панель администратора локального инстанса, перейдите в раздел «Настройка ресурсов» и создайте новый ресурс: | Поле | Значение | | --- | --- | | Название | Ubuntu — или любое удобное | | Протокол | HTTPS | | Проверять первый фактор | Включить при `SendPassword = true`, отключить при `SendPassword = false` | | Поставщики учётных записей | При `SendPassword = true` — один или несколько каталогов, в которых проверяется первый фактор | | Использовать кеширование сессий | Включить, если после успешного входа второй фактор не должен запрашиваться повторно в течение указанного времени | | Длительность кеша | Рекомендуемое значение — 60 минут | После сохранения ресурса скопируйте его ключ (API key ресурса) — он указывается в файле конфигурации PAM-адаптера. Один ресурс может использоваться на любом числе серверов: его ключ указывается в конфигурации каждого из них. Подробнее — в статье [Группа серверов](server-group.md). !!! note "Кеш сессий работает по паре «пользователь + IP»" Для входа по SSH адаптер передаёт адрес подключающегося клиента. При локальном входе и при вызове `sudo` этого адреса нет — тогда адаптер передаёт адрес первого не-loopback интерфейса самого хоста, и кеш привязывается к нему. В [глобальных настройках](../../admin/global-settings.md) убедитесь, что указан корректный API-ключ организации для связи локального инстанса с облаком. ## Установка PAM-адаптера ### Установите модуль из комплекта Адаптер поставляется комплектом: архив с модулем `simple2fa_pam.so` под обе архитектуры, установщиком `install.sh`, шаблоном конфигурации и инструкцией. Распакуйте архив на защищаемом хосте и запустите установщик от root: ```bash sudo ./install.sh ``` Установщик: - определяет архитектуру хоста (`x86_64` или `aarch64`) и берёт из комплекта нужный файл модуля; - находит каталог модулей PAM — тот, в котором лежит штатный `pam_unix.so`, — и копирует модуль туда; - создаёт каталоги `/etc/simple2fa` и `/var/log/simple2fa`; - кладёт в `/etc/simple2fa` шаблон конфигурации `s2fa_conf.toml.example`. Рабочий файл `s2fa_conf.toml` установщик не создаёт и не перезаписывает, строку в `/etc/pam.d/` не добавляет: и то и другое делается вручную — в разделах ниже. !!! warning "Вторая копия модуля в системе" Если установщик сообщает `WARNING: another simple2fa_pam.so is at …`, удалите лишний файл: PAM может загрузить старую копию вместо новой. Каталог модулей PAM можно задать и вручную: ```bash sudo LIBDIR=/usr/lib/security ./install.sh ``` Для справки, где этот каталог обычно находится: в Debian и Ubuntu — `/lib/<архитектура>-linux-gnu/security/`, в Astra Linux — `/usr/lib/security/`, в RHEL и совместимых системах — `/usr/lib64/security/`. ### Создайте конфигурацию Адаптер настраивается файлом `/etc/simple2fa/s2fa_conf.toml`. Скопируйте шаблон, который положил установщик, и отредактируйте его: ```bash sudo cp /etc/simple2fa/s2fa_conf.toml.example /etc/simple2fa/s2fa_conf.toml sudo chmod 0640 /etc/simple2fa/s2fa_conf.toml ``` Файл можно положить и по другому пути — тогда он указывается аргументом `conf=` в строке PAM. Обязательных параметров два: `ApiKey` и `Simple2faUrl`. Остальные можно не указывать, применяются значения по умолчанию. | Параметр | По умолчанию | Назначение | | --- | --- | --- | | `ApiKey` | — | Ключ ресурса из панели. Ключ организации и ключ RADIUS-ресурса не подходят | | `Simple2faUrl` | — | Адрес бэкенда локального инстанса (`local-backend`), без пути. Адрес панели администратора не подходит | | `SendPassword` | `false` | Кто проверяет первый фактор. `true` — пароль передаётся в Simple2FA и проверяется по каталогу организации; `false` — пароль проверяет ОС и на сервер не передаётся | | `Method` | `"auto"` | Способ подтверждения: `auto`, `push`, `telegram`, `max`, `otp`. При `auto` применяется способ, выбранный пользователем | | `AskMethod` | `false` | При `Method = "auto"` и нескольких настроенных способах предложить пользователю выбор | | `OtpPrompt` | `OTP` | Текст приглашения для ввода кода | | `MethodPrompt` | `Способ подтверждения` | Текст приглашения при выборе способа | | `WaitSeconds` | `60` | Сколько ждать подтверждения | | `PollIntervalSeconds` | `2` | Интервал опроса состояния | | `HttpTimeoutSeconds` | `8` | Таймаут одного запроса | | `Timeout` | `45` | Таймаут запроса к инстансам предыдущих версий | | `Debug` | `false` | Подробный журнал. В рабочем режиме отключить | | `LogFile` | `/var/log/simple2fa/simple2fa.log` | Файл журнала, режим `0600` | | `SkipCertValidation` | `false` | Отключить проверку сертификата. Для самоподписанных сертификатов | Пример файла конфигурации: ```toml ApiKey = "<ключ ресурса>" Simple2faUrl = "https://<адрес бэкенда локального инстанса>" SendPassword = false Method = "auto" Debug = false SkipCertValidation = false ``` !!! warning "Строковые значения — в двойных кавычках" Без кавычек файл не разбирается и вход отклоняется; символ `#` в незакавыченном значении обрезает его до конца строки. По той же причине вход отклоняется, если файла нет, он недоступен по правам или в нём не заполнены `ApiKey` и `Simple2faUrl`. Причина отказа пишется в журнал модуля. !!! note "Адрес бэкенда, а не панели администратора" У бэкенда локального инстанса свой адрес, отдельный от адреса панели: при [установке инстанса](../../start/local-instance.md) они задаются как `DOMAIN_API` и `DOMAIN_ADMIN`. В `Simple2faUrl` указываются только протокол, имя хоста и порт бэкенда — путь запроса адаптер добавляет сам. Схема должна совпадать с той, по которой бэкенд опубликован: перенаправлениям адаптер намеренно не следует, поэтому адрес с `http://` при переадресации на HTTPS даёт отказ (в журнале — `http_status=301`). При самоподписанном сертификате укажите `https://` и добавьте `SkipCertValidation = true`. !!! warning "Файл содержит ключ ресурса" Ограничьте доступ к нему правами root. Параметр `UseOTP` устарел. Если он остался в файле со значением `true`, адаптер понимает его как `Method = "otp"` и пишет предупреждение в журнал; в новых установках используйте `Method`. ### Выберите способ подтверждения По умолчанию (`Method = "auto"`) применяется способ, выбранный пользователем в профиле. Чтобы на этом хосте всегда использовался один способ, укажите его явно: `push`, `telegram`, `max` или `otp`. - `Method = "otp"` — адаптер сам запрашивает одноразовый код приглашением из `OtpPrompt`. Способ требует интерактивного ввода. - `AskMethod = true` вместе с `Method = "auto"` — если у пользователя настроено несколько способов, адаптер выведет их нумерованным списком и спросит, каким подтверждать вход. - Если указанный способ у пользователя не настроен, вход отклоняется (в журнале — `method_not_configured`). Подтверждения адаптер ждёт `WaitSeconds` секунд, опрашивая инстанс каждые `PollIntervalSeconds`. !!! note "Сервисы без интерактивного ввода" Некоторые сервисы вызывают адаптер с подавленными приглашениями. Ввести код в таком сценарии нельзя, и вход с `Method = "otp"` или с `AskMethod = true` будет отклонён (`interactive_prompt_suppressed`); подтверждение через push, Telegram и MAX работает и без приглашений. ### Подключите адаптер к PAM Строка подключения адаптера выглядит так: ```text auth required simple2fa_pam.so conf=/etc/simple2fa/s2fa_conf.toml ``` Аргумент `conf=` можно опустить, если файл лежит по пути по умолчанию. Всего модуль понимает три аргумента: | Аргумент | Назначение | | --- | --- | | `conf=/путь/к/s2fa_conf.toml` | Путь к файлу конфигурации | | `method=<способ>` | Способ подтверждения для этого сервиса — `auto`, `push`, `telegram`, `max` или `otp`; перекрывает `Method` из файла | | `debug` | Подробный журнал независимо от `Debug` в файле | Аргумент `method=` позволяет требовать на одном хосте разные способы для разных сервисов — например, одноразовый код для `sudo` и push для входа по SSH. Неизвестные аргументы модуль записывает в журнал и продолжает проверку. Где ставить строку, зависит от режима `SendPassword`: - **`SendPassword = false`** — строка адаптера ставится **после** штатной проверки пароля: после `pam_unix.so` или после подключения общего стека (`@include common-auth`, `substack system-auth`). Иначе подтверждение уйдёт пользователю до проверки пароля, и любой, кто набрал чужой логин, сможет забросать его уведомлениями. - **`SendPassword = true`** — строка ставится вместо штатной проверки пароля: логин и пароль проверит Simple2FA по каталогу организации. Контроли `required` и `requisite` оба отклоняют вход при неуспешной проверке; `requisite` прерывает стек сразу, не выполняя следующие модули. В какие файлы добавлять эту строку — в разделах ниже: у каждого сценария входа свой PAM-стек. ## Локальный вход Локальный вход в Ubuntu настраивается через общий PAM-стек аутентификации. Добавьте строку PAM-адаптера в файл: ```text /etc/pam.d/common-auth ``` !!! warning "Стек общий для всей системы" `common-auth` подключается к большинству сервисов системы, поэтому изменения затронут и другие сценарии входа. Перед изменением сделайте резервную копию файла и держите открытой активную root-сессию до успешной проверки входа. ## Вход по SSH 1. Добавьте строку PAM-адаптера в `/etc/pam.d/sshd`. !!! note "Не добавляйте адаптер дважды" Если строка уже добавлена в `common-auth`, повторно добавлять её в `sshd` не нужно — иначе второй фактор будет запрашиваться дважды. 2. Убедитесь, что в `/etc/ssh/sshd_config` включены поддержка PAM и интерактивная аутентификация: ```text UsePAM yes KbdInteractiveAuthentication yes ``` 3. Перезапустите SSH: ```bash sudo systemctl restart sshd ``` ## Вход по ключу и второй фактор По умолчанию аутентификация по SSH-ключу выполняется в обход PAM-стека, и второй фактор не запрашивается. Чтобы требовать и ключ, и подтверждение, укажите в `/etc/ssh/sshd_config` цепочку методов: ```text UsePAM yes PubkeyAuthentication yes PasswordAuthentication no KbdInteractiveAuthentication yes AuthenticationMethods publickey,keyboard-interactive ``` Первый фактор здесь уже подтверждён ключом, поэтому для такого сценария используйте `SendPassword = false`. После изменения перезапустите SSH: ```bash sudo systemctl restart sshd ``` ## Вход по RDP (xRDP) 1. Установите и запустите xRDP: ```bash sudo apt -y install xrdp sudo systemctl restart xrdp ``` 2. Откройте порт RDP: ```bash sudo ufw allow 3389 ``` 3. Добавьте строку PAM-адаптера в `/etc/pam.d/xrdp-sesman`. 4. Перезапустите xRDP: ```bash sudo systemctl restart xrdp ``` !!! tip "Способ подтверждения для RDP" При подключении по RDP интерактивный ввод одноразового кода может быть недоступен: задайте способ, который ввода не требует — `Method = "push"` в конфигурации или аргумент `method=push` в строке этого стека. ## Исключение группы из проверки Если для отдельной группы (например, `localadmins`) второй фактор запрашивать не нужно, добавьте перед строкой адаптера стандартный модуль `pam_succeed_if`: ```text auth [success=1 default=ignore] pam_succeed_if.so user ingroup localadmins auth required simple2fa_pam.so ``` Для пользователей группы строка адаптера будет пропущена, для остальных — выполнена. Приём применим в любом PAM-стеке. !!! note "Каждое исключение — вход без второго фактора" Оставляйте в группе исключений минимум учётных записей. Точечные исключения для отдельных пользователей удобнее задавать в панели — в [карточке пользователя](../../admin/users.md) или в [политике группы](../../admin/user-groups.md). ## Журнал модуля Модуль пишет по одной строке на событие — в свой файл и в syslog: - файл `/var/log/simple2fa/simple2fa.log` (или путь из `LogFile`), права `0600`; каталог `/var/log/simple2fa` создаётся при установке; - syslog — facility `authpriv`, идентификатор `simple2fa_pam`. Пароль, одноразовый код и ключ ресурса в журнал не попадают. ```bash sudo tail -n 50 /var/log/simple2fa/simple2fa.log sudo journalctl -t simple2fa_pam -e sudo grep simple2fa_pam /var/log/auth.log /var/log/secure 2>/dev/null ``` ## Проверка работы 1. Выполните вход в систему — локально, по SSH или по RDP, не закрывая текущую сессию. 2. Введите логин и пароль пользователя (или пройдите проверку по ключу). 3. Дождитесь запроса второго фактора. 4. Подтвердите вход. 5. После успешной проверки сессия будет предоставлена. !!! note "Если второй фактор у пользователя не настроен" Адаптер покажет ссылку на мастер настройки и отклонит вход. В режиме `SendPassword = true` ссылка появляется только после того, как сервер подтвердил пароль. Результат каждой попытки входа доступен в панели администратора, в разделе [«Попытки авторизации»](../../admin/auth-attempts.md). ## Если что-то не работает Последовательно проверьте, что: - пользователь с таким логином существует в каталоге организации и в Simple2FA и настроил второй фактор; - с машины открыт сетевой доступ к локальному инстансу; - в файле конфигурации указаны ключ ресурса с протоколом HTTPS и адрес бэкенда локального инстанса — со схемой, по которой бэкенд опубликован, и без пути API; - установщик сообщил, в какой каталог положил модуль, и второй копии `simple2fa_pam.so` в системе нет; - строковые значения в файле конфигурации взяты в двойные кавычки, а сам файл доступен root; - строка адаптера добавлена в нужный PAM-стек и стоит в нём на месте, соответствующем выбранному режиму `SendPassword`; - адаптер не подключён дважды — в `common-auth` и в `sshd` одновременно; - пользователь не входит в группу исключений, если она настроена; - системное время на машине и на локальном инстансе синхронизировано; - в панели администратора, в разделе [«Попытки авторизации»](../../admin/auth-attempts.md) отображаются попытки входа и их результат. На время диагностики включите в конфигурации `Debug = true` (или добавьте аргумент `debug` в строку PAM), а после — верните `false`. ### Модуль не загружается Если файл журнала пуст или не создан, загрузка модуля могла не состояться — тогда причина видна в журнале самой службы (sshd, `sudo`, дисплей-менеджера), а не в журнале модуля: ```bash file simple2fa_pam.so uname -m sudo journalctl -u sshd -e | grep -i pam sudo grep -E 'simple2fa_pam|undefined symbol' /var/log/auth.log /var/log/secure 2>/dev/null ``` | Сообщение в журнале службы | Причина | | --- | --- | | `wrong ELF class`, `Exec format error` | Архитектура файла модуля не совпадает с архитектурой хоста | | `GLIBC_2.xx not found` | Модуль собран на более новой версии glibc, чем установлена на хосте | | `cannot open shared object file` | Файла нет в каталоге модулей PAM или он недоступен по правам | | `undefined symbol: pam_sm_acct_mgmt` | Устаревшая сборка модуля | ### Отказы в журнале модуля | Запись | Причина | | --- | --- | | `config file is invalid` | Значения в TOML без кавычек или опечатка в файле | | `http_status=301` или `302` | В `Simple2faUrl` указан `http://`, а бэкенд перенаправляет на HTTPS | | `api_key_rejected` | Указан ключ организации или ключ RADIUS-ресурса вместо ключа этого ресурса | | `http_status=404` или `403` на `check-user` | Пользователя нет в Simple2FA, он неактивен или у него нет доступа к ресурсу | | `setup_required` | Пользователь не настроил второй фактор | | `method_not_configured` | Способ из `Method` у пользователя не настроен | | `interactive_prompt_suppressed` | Сервис вызвал адаптер с подавленными приглашениями, а выбранный способ требует ввода | | `timeout` | Подтверждение не пришло за `WaitSeconds` | ## Альтернатива: подключение через pam_radius Если на серверах уже используется стандартный модуль pam_radius или установка стороннего ПО на защищаемые хосты запрещена, второй фактор для SSH и sudo можно подключить без PAM-адаптера — напрямую к встроенному RADIUS-серверу локального инстанса. Пошаговая инструкция и сравнение способов — в статье [PAM RADIUS](pam-radius.md). ## Смотрите также - [Серверы Linux](index.md) - [ALT Linux](alt-linux.md) - [PAM RADIUS](pam-radius.md) - [Начало работы](../../start/index.md)