mail-nation

Управляем почтой: от домена до конверсий

3 почтовый сервер: архитектура отказоустойчивой системы

Единичный почтовый узел — точка отказа с предсказуемыми последствиями. Выход из строя диска, сетевого интерфейса или процесса MTA может остановить приём писем, оборвать SMTP-сессии и сделать недоступным IMAP.

3 почтовый сервер: архитектура отказоустойчивой системы

Восстановление не всегда быстрое: пока администратор разбирается с причиной, входящие сообщения остаются в очередях отправителей и релеев, а пользователи не могут открыть свои ящики.

Три узла помогают распределить нагрузку и локализовать отказ, но само число серверов ничего не гарантирует. Если все три одновременно выполняют одну и ту же роль, а данные и сессии не согласованы, получатся три точки возможного сбоя вместо одной — без ясного способа переключения. Надёжность появляется из разделения функций, продуманной маршрутизации и проверенного восстановления данных.

Разделение ролей в трёхзвенной архитектуре

Трёхзвенная архитектура описывает три функциональных слоя: приём и фильтрацию почты, проксирование пользовательских подключений и хранение ящиков. Это не означает, что в системе ровно три физических машины. В приведённой ниже схеме пять узлов: два шлюза, один прокси и два хранилища. Такое распределение даёт резервирование для входящего SMTP и хранения, но прокси пока остаётся одиночным узлом и отдельной точкой отказа.

УзелОсновная рольКлючевые компоненты
Edge-01, Edge-02Входящие SMTP-шлюзыPostfix, фильтрация, антиспам, очередь
Proxy-01Фронтенд для клиентских подключенийNginx mail, интеграция с Dovecot Director
Mbox-01, Mbox-02Хранилища почтовых ящиковDovecot, LMTP, maildir или mdbox

Шлюзы принимают корреспонденцию извне, применяют политики фильтрации и передают сообщения на доставку. Postfix сохраняет письма в очереди, если следующий компонент временно недоступен; это не то же самое, что долговременное хранение ящиков. Прокси принимает пользовательские соединения и направляет их к нужному хранилищу. Mbox-узлы обслуживают ящики и работают с почтовыми данными.

В этой схеме резервирование есть не везде. Два Edge-узла могут принимать SMTP-трафик параллельно или через внешний балансировщик и DNS-политику. Два Mbox позволяют распределить пользователей и пережить отказ одного узла, если данные и назначение ящиков организованы соответственно. Но Proxy-01 остаётся одиночным: при его отказе клиенты потеряют доступ, даже если хранилища и шлюзы продолжают работать. Чтобы устранить эту точку отказа, нужны как минимум два фронтенда и механизм переключения — например, балансировщик или виртуальный IP с отказоустойчивым управлением.

Три функциональных слоя — не обязательно три машины. А резервирование появляется только там, где есть второй узел и понятный механизм переключения.

Число узлов каждой роли выбирают по нагрузке и требуемому уровню доступности. При этом мало добавить сервер: нужно определить, кто хранит состояние, куда направляются новые соединения и что произойдёт с уже открытыми сессиями. Иначе автоматическое переключение может направить пользователя на сервер, где его ящика нет.

Внутри одной роли важна совместимость программного окружения. Одинаковые версии и согласованные настройки Dovecot упрощают переключение, но не заменяют план миграции данных: обновления форматов индексов и изменение параметров хранилища требуют отдельного порядка работ. Конфигурацию следует вести централизованно или хотя бы проверять на различия между узлами перед вводом их в пул.

Dovecot Director и контроль сессий

Почтовый ящик обычно должен обслуживаться согласованным набором процессов. Если подключения одного пользователя без координации попадают на разные хранилища, серверы могут работать с разными копиями данных или независимо обновлять состояние ящика. Последствия зависят от конкретной схемы хранения: от устаревших индексов и конфликтов блокировок до потери доступа к части сообщений.

Dovecot Director помогает закрепить пользователя за определённым бэкендом. Вместо случайного выбора хранилища при каждом подключении директор поддерживает назначение пользователя и направляет его сессии на соответствующий Mbox. Это особенно важно, когда ящики физически распределены по узлам, а не доступны всем бэкендам через общее хранилище.

Director не реплицирует сами письма и не делает хранилища взаимозаменяемыми автоматически. Его задача — координация маршрутизации. Если Mbox-узел перестал работать, одного переназначения пользователя недостаточно: целевой сервер должен иметь доступ к актуальным данным, иначе клиент подключится к доступному, но пустому ящику.

В типовой конфигурации Dovecot Director взаимодействует с другими узлами своей группы и использует информацию о пользователях, полученную при аутентификации или запросе userdb. Конкретные поля и настройки зависят от версии Dovecot и принятой схемы конфигурации. Назначение бэкенда должно соответствовать фактическому расположению ящика, а веса узлов — отражать их ёмкость, если система распределяет между ними новых пользователей.

Порт межсерверного взаимодействия, в том числе часто используемый в конфигурациях Director TCP 9090, нельзя оставлять доступным из интернета. Доступ к нему ограничивают внутренней сетью и правилами межсетевого экрана. Кроме того, Director должен быть развернут с учётом отказа: один экземпляр не обеспечивает координацию, если сам узел недоступен. Конкретная топология и синхронизация зависят от версии и документации Dovecot, поэтому конфигурацию нужно проверять не только на запуске, но и при потере одного из участников.

Сценарий переключения стоит прогнать заранее: отключить один Mbox, проверить поведение новых соединений, убедиться, что старые сессии завершаются ожидаемо, а пользователь после восстановления попадает к актуальному ящику. Если в системе есть миграция пользователей между бэкендами, её также следует испытывать отдельно. Перенос — это не просто смена адреса сервера в маршрутизации: необходимо согласовать данные и момент переключения, чтобы новые письма не разошлись между старым и новым местом хранения.

Nginx как фронтенд IMAP/POP3/SMTP

Клиентам удобнее подключаться к одному публичному имени, не зная, на каком сервере лежит конкретный ящик. Эту задачу может решать фронтенд с Nginx mail-модулем. Он принимает соединение, получает данные для аутентификации и передаёт запрос на выбранный сервер. Сам модуль не следует описывать как обычный HTTP-балансировщик: для почтовых протоколов выбор бэкенда обычно связан с ответом внешнего сервиса аутентификации.

В Nginx mail модуль обращается к auth-серверу по HTTP. Сервис проверяет пользователя и возвращает параметры проксирования — в частности, адрес целевого сервера и необходимые сведения о протоколе. Поэтому распределение почты между серверами должно быть реализовано в логике этого сервиса или связанной с ним системы назначения ящиков. Там учитывают, где хранится ящик пользователя, доступен ли соответствующий Mbox и требуется ли направить соединение через Dovecot Director. Простая ротация адресов не подходит, если на разных узлах находятся разные пользовательские данные.

Это различие важно и при отказе. Nginx mail не выбирает для каждого клиента произвольный сервер из upstream по round-robin так, как это может происходить в HTTP-конфигурации. Auth-сервис должен вернуть пригодный бэкенд. Проверка состояния узлов, исключение неисправного хранилища и правила переключения должны быть предусмотрены в этой логике или во внешнем слое, который сообщает auth-сервису актуальное назначение.

Упрощённый путь IMAPS выглядит так:

1. Клиент подключается к фронтенду по TCP 993.

2. Nginx устанавливает или принимает TLS-соединение согласно конфигурации.

3. Модуль mail запрашивает у auth-сервиса результат проверки и параметры проксирования.

4. После успешной проверки соединение направляется на указанный Dovecot-бэкенд.

5. Dovecot обслуживает сессию; фронтенд не подменяет собой хранилище и не синхронизирует его данные.

Для POP3S применяется похожая схема с публичным портом TCP 995. IMAP и POP3 без TLS обычно не открывают клиентам в публичной сети, если нет отдельной обоснованной потребности. SMTP submission обслуживают отдельно: пользователи отправляют почту через авторизованный сервис, обычно на TCP 587 или 465, а входящая межсерверная почта идёт на TCP 25. Не всякую почтовую службу обязательно проксировать через один и тот же Nginx: выбор зависит от схемы аутентификации, требований к TLS и того, какой компонент фактически принимает конкретный протокол.

СервисТипичный внешний портНазначение
SMTPTCP 25Приём почты от других серверов
SMTPSTCP 465Отправка почты клиентом с TLS
SubmissionTCP 587Отправка почты клиентом с авторизацией
POP3TCP 110Получение почты без обязательного шифрования
POP3STCP 995Получение почты через TLS
IMAPTCP 143Работа с почтовым ящиком без обязательного шифрования
IMAPSTCP 993Работа с почтовым ящиком через TLS

Таблица показывает распространённые порты, но не заменяет сетевую схему. Порт, открытый на внешнем интерфейсе, должен соответствовать реально работающей службе и правилам доступа. Между прокси и Mbox тоже нужны отдельные разрешения: внутренний трафик не становится безопасным только потому, что он не выходит в интернет.

TLS можно завершать на фронтенде и строить отдельное защищённое соединение до бэкенда. Если внутренний сегмент пересекает недоверенную сеть, шифрование между компонентами особенно важно. Сертификаты фронтенда и бэкендов могут выпускаться разными центрами сертификации, но Nginx должен доверять сертификатам серверов, с которыми устанавливает защищённое соединение. Иначе проверка сертификата либо завершится ошибкой, либо окажется отключена — второй вариант маскирует проблему, а не решает её.

LMTP и доставка от MTA к MDA

После приёма сообщения Postfix должен передать его компоненту, который доставит письмо в ящик. Для связки Postfix и Dovecot распространён LMTP — протокол локальной доставки, позволяющий MTA получить результат обработки от принимающей стороны. Он удобен, когда Dovecot отвечает за доступ к ящикам, квоты и правила доставки.

Путь письма в такой схеме состоит из нескольких этапов:

1. Postfix принимает сообщение и помещает его в очередь.

2. Проверки и транспортные правила определяют, куда доставлять письмо.

3. Postfix передаёт сообщение Dovecot по LMTP.

4. Dovecot определяет ящик получателя, записывает сообщение в выбранное хранилище и возвращает статус доставки.

5. Postfix удаляет успешно доставленное сообщение из очереди; при временной ошибке оставляет его для повторной попытки.

LMTP можно использовать через Unix-сокет, когда компоненты работают на одном хосте и локальный доступ соответствует требованиям безопасности. Для удалённого Dovecot-бэкенда одним из вариантов служит TCP-соединение. Конкретный выбор зависит от размещения компонентов, сетевой сегментации и требований к контролю доступа. Сам факт использования TCP не гарантирует отказоустойчивость: нужны правильная маршрутизация получателя, обработка временных ошибок и понятное поведение очереди при недоступности хранилища.

LMTP через TCP — один из вариантов связи Postfix-шлюза с удалённым Dovecot-бэкендом, а не единственный способ организации доставки.

Важнее всего не отправлять письмо на случайный Mbox. Если пользователи распределены по разным узлам, Postfix должен знать, где находится конкретный ящик, либо передавать доставку компоненту, который выполняет такое назначение. Это может быть транспортная карта, каталог пользователей или отдельная логика маршрутизации. При выборе механизма нужно проверить, что он одинаково обрабатывает основной сервер, резервный маршрут и временную недоступность узла.

Настройка очереди — часть отказоустойчивости. Если Mbox временно не отвечает, шлюз должен получить временную ошибку и повторить доставку позднее, а не считать сообщение доставленным. Если сервер отвечает постоянной ошибкой, Postfix может прекратить попытки и сформировать отказ отправителю. Поэтому аварийный сценарий нужно тестировать на реальных кодах ответа, а не только проверкой доступности TCP-порта.

Целостность данных при распределении нагрузки

Балансировка подключений и сохранность писем — разные задачи. Nginx может принять соединение и направить его на сервер, но это не означает, что на сервере есть нужный ящик или свежая копия сообщений. Для каждого пользователя архитектура должна отвечать на три вопроса: где хранится его почта, как определяется нужный Mbox и что произойдёт с данными при потере этого узла.

Есть несколько подходов к отказоустойчивости хранилища, и ни один не следует включать в схему только по названию:

  • Репликация блочного устройства или файловой системы. Она может сократить время восстановления, но требует согласованного переключения и понимания того, какой узел имеет право записывать данные. Одновременная запись в две несогласованные копии создаёт риск расхождения.
  • Копирование на резервный узел. Репликация с задержкой или резервное копирование помогают восстановить данные, но не всегда дают немедленно актуальную копию. Допустимая потеря изменений зависит от частоты и способа копирования.
  • Общее хранилище. Несколько серверов могут обращаться к одним данным, если это поддерживает выбранная файловая система и обеспечены нужные блокировки. Само по себе общее подключение диска не делает конкурентную запись безопасной.
  • Миграция пользователя между Mbox. При выводе узла из эксплуатации сначала копируют и сверяют данные, затем меняют назначение и проверяют доставку и клиентский доступ. Переключение маршрута без миграции оставит пользователя без его ящика.

Выбор формата хранения — maildir или mdbox — тоже влияет на эксплуатацию, но не отменяет резервное копирование. Индексы Dovecot обычно можно восстановить, тогда как сами сообщения являются первичными данными. Бэкап нужно проверять восстановлением: наличие успешного задания в журнале не доказывает, что из копии получится собрать рабочий ящик.

Для пользователей и доменов нужен общий источник аутентификации либо гарантированно согласованные базы. PostgreSQL, LDAP и другие каталоги помогают поддерживать единые учётные записи, пароли и квоты для нескольких Mbox. Локальные файлы пользователей могут быть уместны в небольшой системе, но при ручной синхронизации быстро становятся источником расхождений. Важно определить не только место хранения пароля, но и способ получения сведений о расположении ящика.

Сетевые правила должны соответствовать ролям. Внешним отправителям нужен доступ к SMTP-шлюзам; клиентам — к опубликованным службам; прокси — к auth-сервису и нужным бэкендам; шлюзам — к LMTP и необходимым каталогам. Межсерверные порты Director и административные интерфейсы следует ограничить внутренними адресами. Чем шире доступ между сегментами, тем больше последствий у компрометации одного узла.

Мониторинг полезнее строить по цепочке доставки, а не по списку процессов. Следует видеть состояние очередей Postfix, результаты LMTP-доставки, доступность пользовательских протоколов, свободное место на Mbox и ошибки аутентификации. Если письма копятся на Edge, а IMAP продолжает работать, это разные инциденты; если прокси отвечает, но не может получить назначение от auth-сервиса, проблема находится на другом участке. Такие различия сокращают время поиска причины.

Для проверки отказоустойчивости достаточно не декларации о резервировании, а нескольких контролируемых испытаний: отключить один шлюз и убедиться, что приём продолжается; сделать недоступным один Mbox и проверить, как обрабатываются новые и существующие сессии; остановить LMTP и проследить за очередью; восстановить тестовый ящик из резервной копии. Результат каждого испытания должен соответствовать заранее принятому сценарию, включая то, что увидит пользователь и что произойдёт с письмом.

Внешние материалы тоже требуют осторожной оценки: даже в другой инженерной области полезно различать устойчивость системы и привычное описание её схемы. Для почты этот принцип вполне конкретен: три функциональных слоя не равны трём резервным узлам, а работающий фронтенд не подтверждает целостность ящиков.

Отказоустойчивый почтовый сервер — не одна удачная настройка, а согласованная система шлюзов, прокси, хранилищ и маршрутизации. Сначала определяют, где лежат данные и кто назначает бэкенд, затем проектируют переключение и только после этого добавляют узлы. В схеме с Edge-01, Edge-02, Proxy-01, Mbox-01 и Mbox-02 уже есть резервирование шлюзов и хранилищ, но прокси остаётся одиночной точкой отказа. Это не делает архитектуру бесполезной; это точно показывает, какую часть системы ещё предстоит резервировать.

Частые вопросы

Почему три почтовых сервера не гарантируют отказоустойчивость?
Если все серверы выполняют одинаковые роли без согласования данных и сессий, они становятся тремя отдельными точками сбоя вместо одной.
Зачем нужен Dovecot Director в архитектуре почтового сервера?
Он координирует маршрутизацию и закрепляет пользователя за определенным хранилищем, предотвращая ситуацию, когда сессии одного клиента попадают на разные бэкенды с разными копиями данных.
Какую роль выполняет Nginx в почтовой системе?
Nginx с mail-модулем выступает фронтендом, который принимает клиентские подключения и направляет их на нужный сервер на основе данных от внешнего сервиса аутентификации.
Как Postfix доставляет письма в ящики в распределенной системе?
Для передачи почты от MTA к MDA используется протокол LMTP, который позволяет Postfix получать статус доставки от Dovecot и корректно обрабатывать временные ошибки.
Как проверить отказоустойчивость почтовой системы?
Необходимо проводить контролируемые испытания: отключать шлюзы и хранилища, проверяя поведение очередей, доступность сессий и корректность переключения на резервные узлы.