MFA не отвечает: как мы строили отказоустойчивый облачный сервис аутентификации

Привет! Меня зовут Николай Киселев, я инженер по информационной безопасности в облачном провайдере Nubes. В этой статье хочу рассказать, как (а главное – зачем) мы делали наш сервис многофакторной аутентификации отказоустойчивым. Ну и почему доступность MFA – это не только эксплуатационная, но и полноценная бизнес-задача.
Почему доступность MFA критична для бизнеса
При нормальной работе MFA пользователь вводит логин и пароль, после чего защищаемая система обращается к сервису MFA за подтверждением второго фактора. То есть сервис должен принять запрос, обработать его и вернуть ответ. Если этот обмен нарушен, система не может убедиться, что второй фактор действительно пройден, и сотрудники просто не могут авторизоваться в своих учетках.
Например, в начале рабочего дня работники подключаются к корпоративной сети через VPN. Логин и пароль введены правильно, но VPN-шлюз не получает ответ от MFA, запрос завершается по тайм-ауту, а подключение отклоняется. Для пользователя это выглядит как обычная ошибка входа. Он повторяет попытку, перезапускает VPN-клиент, проверяет пароль и обращается в поддержку. Когда то же самое одновременно происходит у десятков или сотен сотрудников, проблема быстро перестает быть локальной. Люди не могут добраться до внутренних систем, начать работу с корпоративными приложениями или подключиться к удаленным рабочим столам. При этом уже установленные сессии могут продолжать работать, а новые нет, поэтому масштаб инцидента растет постепенно и не всегда сразу очевиден.
Параллельно службе поддержки и администраторам еще нужно определить источник сбоя. Причина может находиться в VPN-шлюзе, каталоге пользователей, сети, агенте интеграции или самом сервисе MFA. Пока идет диагностика, рабочее время теряют уже не отдельные пользователи, а целые подразделения. Таким образом, даже короткий простой компонента, который сам по себе не является бизнес-приложением, влияет на доступность сразу нескольких бизнес-систем.
А если недоступность MFA совпала с другим инфраструктурным инцидентом? Это катастрофа совсем другого масштаба! Инженерам требуется срочно войти в консоль управления, систему виртуализации или административный интерфейс, доступ к которому также защищен вторым фактором. Получается, чтобы устранить аварию, нужен привилегированный доступ, но получить его нельзя из-за отказа системы, которая этот доступ защищает.
Если аварийные учетные записи и процедура обхода не были подготовлены заранее, команда оказывается перед плохим выбором: ждать восстановления MFA или в спешке отключать второй фактор.
И именно в этом случае про MFA вспоминают чаще всего. Не когда он выполнил свою задачу и остановил попытку входа с украденным паролем, а когда все сломалось и бизнес теряет деньги из-за простоя.
Мы хотели создать облачный сервис MFA, для которого доступность была бы одним из свойств безопасности, поэтому мы серьезно подошли к вопросу его проектирования. Не просто «запустим сервер аутентификации и настроим резервное копирование», а «зарезервируем сами сервисы, базу данных и сетевые компоненты». Плюс в список задач впишем контроль их состояния и продумаем план, как действовать при недоступности целой площадки.
Сначала отказоустойчивая инфраструктура, потом отказоустойчивая MFA
В основе решения MFASOFT лежит агентская модель с разделением на два контура. Secure Authentication Server (SAS) размещается в облаке Nubes: он хранит политики MFA, сведения о пользователях и аутентификаторах и принимает решения по запросам второго фактора. Разработанные MFASOFT агентские компоненты устанавливаются в инфраструктуре заказчика: они встраивают MFA в конкретные точки входа и переводят запросы в формат, понятный SAS.
Для разных точек входа MFASOFT предусматривает свои способы интеграции. В RADIUS-сценарии используется шлюз из FreeRADIUS и агента FRA в Docker-контейнере: сетевое устройство передает ему RADIUS Access-Request, а агент обращается к SAS по HTTPS. Для ADFS и Keycloak используются плагины, включенные в штатный процесс аутентификации. При прямой интеграции приложение вызывает Web API методом POST на публикацию сервиса; в ответ SAS возвращает JSON с полями Auth, Details и Time. В итоге внутри контура заказчика сохраняется привычный для системы протокол, а до облачного сервиса запрос доходит по защищенному HTTPS-соединению.
Базовые принципы серверной архитектуры также описаны в руководстве SAS: несколько серверов аутентификации могут работать за внешним веб-балансировщиком без привязки агента к конкретной ноде, а для приемлемой доступности рекомендуется дублировать используемые модули и базу данных.
Эту схему мы взяли за основу основной площадки Nubes и развернули две ноды сервера аутентификации на выделенных виртуальных машинах в режиме active-active. Дополнительно настроили anti-affinity: платформа виртуализации размещает ВМ на разных физических узлах, поэтому отказ или обслуживание одного хоста не должны одновременно вывести из работы обе ноды SAS.
Перед двумя SAS-нодами разместили L7-балансировщик, на который перенесли завершение TLS-сессии. Он проверяет доступность веб-эндпоинта каждой ноды и исключает из пула сервер, переставший отвечать. Sticky sessions нам не потребовались: серверы аутентификации не хранят локальное состояние, к которому нужно вернуть следующий запрос. Данные пользователей, политик и аутентификаторов находятся в общей базе, поэтому каждый новый запрос можно направить на любую исправную ноду SAS. Так stateless-модель приложения мы сразу использовали и для распределения нагрузки, и для переключения при отказе.
Документация SAS задает общую схему с внешним веб-балансировщиком. На инфраструктурном уровне мы усилили входную точку: предусмотрели адаптивное масштабирование в зависимости от объема запросов, поэтому ее пропускная способность не привязана к одному статичному экземпляру балансировщика. Дополнительно защитили интернет-канал от объемных DDoS-атак на L3-L4, чтобы сетевой и транспортный мусор отсекался до прикладных компонентов MFA.
Схему базы данных также реализовали в соответствии с рекомендациями SAS: двухузловой кластер MariaDB с репликацией active-active. Оба узла принимают операции чтения и записи и хранят копию базы SAS. В конфигурации приложения указали URI обеих нод БД; на разных серверах SAS их можно задать в разном порядке. Если текущее соединение недоступно, приложение использует следующий адрес. В нашей конфигурации это дало client-side failover без отдельного балансировщика перед СУБД.
В результате отказ отдельной ВМ приложения, физического хоста или одной ноды БД не останавливает обработку новых запросов. При этом в процессе сборки проявился следующий риск: такая схема может скрыть деградацию, потому что сервис продолжает отвечать, хотя запас отказоустойчивости уже уменьшился. Поэтому следующим этапом для нас стал мониторинг.

Архитектура архитектурой, а мониторинг по расписанию
После сборки кластера мы перешли к следующему вопросу: как увидеть деградацию раньше пользователей. Отказоустойчивость некоторое время скрывает проблему: одна нода уже потеряна, но вторая продолжает принимать запросы. Снаружи сервис доступен, внутри система уже работает без запаса на следующий отказ.
В Zabbix мы контролируем два уровня. На инфраструктурном собираем загрузку процессоров и памяти, свободное место и активность дисков, сетевую доступность, состояние виртуальных машин и системных служб. Это позволяет отличить прикладную ошибку от нехватки ресурсов или проблемы на уровне ОС и виртуализации.
На прикладном уровне штатных метрик оказалось недостаточно, поэтому мы добавили отдельные элементы данных для компонентов MFA. Они показывают количество и результаты попыток аутентификации, ошибки и время обработки запросов, доступность сервисов SAS, состояние нод базы данных и репликации. Проверка только TCP-порта здесь не подходит, так как процесс может принимать соединение, но не выполнять аутентификацию, поэтому для критичных компонентов мы контролируем именно рабочее состояние.
Поверх элементов данных настроены триггеры. Алерт формируется не только при полной недоступности, но и при потере одной из active-active нод, нарушении репликации, отсутствии данных мониторинга, росте ошибок или времени ответа. Так дежурная смена получает сигнал в момент деградации, пока оставшаяся часть кластера еще обслуживает запросы.
События аудита и журналы компонентов централизованно поступают в SIEM. Штатная syslog-интеграция SAS передает действия пользователей и администраторов, а также ошибки сервисов. В SIEM эти события сопоставляются с данными других систем. Для значимых последовательностей настроены корреляции и алерты. Это помогает увидеть не только отказ компонента, но и контекст, в котором он возник.
Дальше алерт должен превратиться в действие. Дежурные администраторы 24/7 проверяют затронутый компонент и связанные метрики, выполняют согласованный плейбук и при необходимости эскалируют инцидент профильным инженерам. Мы заранее фиксируем порядок проверки и критерии эскалации, чтобы во время сбоя не определять их заново.
Отдельный уровень — резервное копирование. Реплика MariaDB повышает доступность, но повторяет и логическую ошибку: удаление или некорректное изменение быстро попадет на второй узел. Поэтому копии БД сохраняются на выделенных дисках отдельно от рабочих данных, а в мониторинге контролируются статус задания, актуальность последней копии и свободное место в хранилище. Дополнительно создаются резервные копии виртуальных машин: БД нужна для восстановления данных, копии ВМ — для возврата серверного контура с его конфигурацией.
Получилась цепочка «метрика или событие → триггер → алерт → плейбук → эскалация», дополненная независимым восстановлением из резервных копий. Но все эти механизмы остаются внутри основной площадки. Для сценария ее полной недоступности мы подготовили отдельный резервный контур.

Без резервирования все равно опасно
Архитектура
Кластер основной площадки закрывает отказ отдельных серверов, базы данных и части сетевых компонентов. Но при его проектировании мы отдельно рассматривали сценарий, в котором проблема затрагивает площадку целиком: например, становится недоступна ее внешняя сеть или общая инфраструктура. Размещать еще несколько нод внутри того же контура в такой ситуации бессмысленно. Они сохранят общие точки отказа. Поэтому следующий уровень мы вынесли на отдельную резервную площадку.
На резервной площадке выделена одна нода, на которой заранее подготовлены контейнеры SAS и MariaDB. В штатном режиме прикладной сервис не принимает запросы агентов. Резервная MariaDB используется как асинхронная реплика основной базы и защищена параметром read_only, поэтому не становится вторым источником записи до процедуры переключения.
Между площадками организовано защищенное соединение Site-to-Site VPN. Через него изменения основной MariaDB асинхронно передаются на резерв, а конфигурационные файлы и локальные резервные копии синхронизируются отдельно. Поток направлен от основной площадки к резервной: возможная задержка репликации контролируется перед запуском переключения.
Межплощадочный доступ мы ограничили по принципу минимальных привилегий. Резервная сторона получает только те права, которые нужны для чтения данных, репликации и синхронизации, но не может изменять рабочую базу на основной площадке.
Но как мы заставим агентов обращаться к новой площадке в момент аварии на основой?
Здесь нам помогает особенность агентской модели: в конфигурации агента указан не IP-адрес конкретного сервера или площадки, а DNS-имя сервиса. Для агента точка подключения остается прежней, меняется только адрес, который возвращает DNS.
В штатном режиме запись разрешается во входной адрес L7-балансировщика основной площадки. После запуска и проверки резерва то же имя переводится на внешний IP-адрес с резервной площадки. TTL записи равен 10 минутам: после истечения срока жизни рекурсивные резолверы и локальные кэши запрашивают актуальный адрес, а новые HTTPS-запросы агентов уходят в резервный контур.
У каждой площадки собственная входная точка L7. Поэтому межплощадочное переключение не зависит от балансировщика, размещенного только в одном контуре: если основная площадка вместе с ее L7-балансировщиком недоступна, DNS-запись можно направить на резервный L7-вход. Иначе общий балансировщик сам стал бы межплощадочной точкой отказа.
Конфигурацию на стороне заказчика менять не нужно. Мы проверяли этот сценарий на работающих агентах: после обновления DNS они успешно продолжали аутентификацию через резерв. Фактическое время перехода складывается из активации сервисов, технической проверки и обновления DNS-кэшей.
Сценарии переключения при аварии
Мы не запускаем его автоматически при единичном алерте. Сначала дежурная смена подтверждает масштаб проблемы и оценивает, можно ли восстановить основную площадку быстрее, чем активировать резерв. Это помогает избежать переключения из-за кратковременного сетевого сбоя и ситуации, когда одновременно работают два независимых контура с расходящимися данными.
После проверки и принятия решения ответственный администратор вручную запускает подготовленный скрипт. Он последовательно останавливает асинхронную репликацию и проверяет состояние резервной БД, снимает read_only, а затем переводит подготовленные контейнеры сервиса в рабочий режим. Решение о переходе принимает человек; скрипт выполняет только техническое переключение.
Автоматизация снижает количество ручных действий, но не принимает решение о направлении пользовательского трафика. После завершения скрипта дежурные администраторы проверяют доступность и корректную работу модулей SAS по заранее согласованному плейбуку. Только после успешной проверки DNS-записи переводятся на резервную площадку. Затем мы контролируем поступление запросов от агентов и результаты аутентификации уже в рабочем потоке.
С этого момента резервная площадка работает самостоятельно и становится источником актуальных изменений. Это важно учитывать во втором сценарии – при возврате на основную площадку. Простого обратного переключения DNS здесь недостаточно: за время работы резерва в базе могли появиться новые события, настройки и изменения учетных данных.
Поэтому сначала мы восстанавливаем и проверяем основную инфраструктуру, затем приводим данные площадок в согласованное состояние. После этого повторно тестируем аутентификацию на основной площадке и только затем возвращаем на нее DNS-записи. Когда рабочий трафик снова стабильно обрабатывается основным кластером, резерв переводится в режим ожидания и восстанавливается штатная синхронизация: основа → резерв.
Раз в полгода мы проверяем сам сценарий запуска резерва: актуальность данных и конфигураций, работу автоматизированного скрипта, запуск компонентов и прохождение тестовой аутентификации. Такая проверка нужна не для демонстрации наличия резервной площадки, а чтобы инструкция, доступы и последовательность действий оставались рабочими к моменту реального инцидента.

Вместо заключения: куда двигаться дальше
В текущей схеме отказ отдельных компонентов обрабатывается автоматически внутри основной площадки, а переход между площадками остается управляемым: решение принимает дежурная смена, технические операции выполняет скрипт, направление трафика меняется через DNS. Полностью автоматическое переключение без механизма, который гарантирует единую согласованную базу, создало бы риск одновременной записи в два разошедшихся контура.
Следующий вариант, который мы прорабатываем, — три активные площадки, Galera Cluster и GSLB. Три независимые голосующие ноды БД нужны для устойчивого кворума при отказе площадки или разрыве межплощадочной связи, а GSLB сможет направлять агентов только на доступные контуры. При этом сам GSLB и авторитативный DNS также должны быть распределены: иначе автоматизация просто перенесет общую точку отказа в управляющий слой.
До внедрения нужно проверить влияние межплощадочных задержек, поведение кворума при сетевом разделении, повторное присоединение нод и распространение DNS-ответов. Если вы строили Galera между тремя площадками и закрывали их GSLB, расскажите в комментариях, какие ограничения проявились в эксплуатации и на что нам следует обратить внимание при тестах такой схемы.
KioskNews shows a cleaned-up reading view extracted from the publisher’s page — the original always lives on their site, not ours.