Нет, это не Рио-де-Жанейро. Это гораздо хуже
(О. Бендер)
Прелюдия
Имеется несколько тематических списков рассылки одного крупного портала. В течении дня может пройти несколько рассылок по разным спискам. В самом большом списке более 200К подписчиков. И со всем этим успешно справлялся не самый мощный сервер (далее мейлер) с единственным белым адресом. Так что в течении 1,5-2 часов все 200К успешно уходили
Однако есть у нас один национальный мейл-провайдер (далее mailhub.tld), который вдруг, неожиданно, со своей стороны установил ограничения и в логах зачастила запись
421 Too many concurrent SMTP connections from this IP address; please try again later
Как выснилось из переписки с саппортом, они дают не более 8 одновременных подключений, не более 100 писем в одном подключении и не более 200 писем в секунду. И никак не собираются менять лимиты даже для конторы с громким именем в своей стране
Необходимо что б Вы исправили ситуацию с количеством подключений и вопрос будет решён автоматически
Таким образом они защищаются от спама. И это хорошо для них, но плохо для нас. Мы ввели рекомендуемые ограничения для домена mailhub.tld. Почта для остальных доменов шла на общих основаниях — 90 одновременных подключений. И теперь не только мы — люди, но и наш мейлер был удивлен таким раскладом и рекомендовал поднять лимиты
warning: mail for mailhub.tld is using up 6284 of 6284 active queue entries
warning: you may need to increase the main.cf mailhubtld_destination_concurrency_limit from 8
Так как подписчиков, у которых ящики на mailhub.tld более чем 60% списка рассылки (ок. 120К) то при таких ограничениях очередь стала быстро расти. И подписчики, у которых ящики отличные от mailhub.tld не могли своевременно получить почту. Человек выписавший с сайта счет мог получить его через 4-8 часов. Ясно, что с этим нужно было что-то делать

Слева два широких высоких пика это две рассылки по 200К подписчиков. Такие рассылки прошли быстро. Из-за введеных ограничений рассылка на mailhub.tld длилась 11 часов (ок. 120К подписчиков)
Варианты выхода
Их было всего два: переговоры с большими начальниками mailhub.tld и расширение парка мейлеров. Последний вариант был с вопросами, а именно:
- Нужно время для инсталяции, настройки, проверки новых мейлеров (На тот момент речь шла о дополнительных виртуальных серверах)
- Усложняется администрирование
- mailhub.tld должен будет еще «научится» понимать, что новые мейлеры не спамеры
- Чтоб выйти на цифру 90, нам нужно 11 таких мейлеров, исключительно ради mailhub.tld (Важно решить проблему доставки почты именно для пользователей этого домена)
- Нужны дополнительные ip-адреса. Аренда одного адреса — 1 евро/мес (Ерунда конечно, но все же)
- Через пол-года к примеру они введут ограничения с 8 до 3, и что, нам опять расширять парк мейлеров?
Мы занимаемся рассылками с 2011 года. И никаких проблем с mailhub.tld никогда не было. Более того, мы сами нашим подписчикам рекомендовали этот сервис как беспроблемный
Переговоры с ними ни к чему не привели. Позже пришел еще один ответ от их саппорта
Это ограничение на всех одинаковое, селективного вайтлиста нет, т.к. ограничения общесистемные
Такие дела 🙁
Задача
Разделить исходящую почту к mailhub.tld и другим мейл-провайдерам посредством настройки мультиинстанс postfix. Вся входящая почта должна приходить как и раньше через основной инстанс
Текущее состояние
Есть виртуальный мейлер с внешним и внутренным интерфейсом строго для рассылки и приема почты. В качестве MTA выступает posftix. В качестве dns-сервера unbound, который используется как форвардер. Имена хостов внутренней сети прописаны в /etc/hosts. Вся исходящая почта подписывается opendkim. x.x.x.92 — белый адрес внешнего интерфейса, 192.168.55.92 — серый адрес внутреннего интерфейса мейлера
Поехали!
Все действия выполняются на продакшене. ОС Gentoo
Берем у провайдера белые адреса x.x.x.15/24 x.x.x.16/24 и прописываем их дополнительными на внешний интерфейс. Аналогично с серыми адресами 192.168.55.15/24 192.168.55.16/24. Сразу все оформляем в конфиге. /etc/conf.d/net должен выглядеть примерно так:
config_eth0="x.x.x.92/24 x.x.x.15/24 x.x.x.16/24" routes_eth0="default via x.x.x.1" config_eth1="192.168.55.92/24 192.168.55.15/24 192.168.55.16/24"
И перезагружаем интерфейсы
rc-service net.eth0 restart rc-service net.eth1 restart
Команда ip addr должна показать следующую картину (лишнее убрал):
eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 state UP inet x.x.x.92/24 brd x.x.x.255 scope global eth0 inet x.x.x.15/24 brd x.x.x.255 scope global secondary eth0 inet x.x.x.16/24 brd x.x.x.255 scope global secondary eth0 eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 state UP inet 192.168.55.92/24 brd 192.168.55.255 scope global eth1 inet 192.168.55.15/24 brd 192.168.55.255 scope global secondary eth1 inet 192.168.55.16/24 brd 192.168.55.255 scope global secondary eth1
Порядок. Теперь переводим postfix в режим мультиинстанса. В этом режиме postfix будет работать с папками, конфигами, очередью и pid-файлами каждого дополнительного инстанса отдельно
postmulti -e init postmulti -I postfix-15 -G mailout -e create postmulti -I postfix-16 -G mailout -e create
Все созданные конфиги безопасны и закрыты от запуска параметром master_service_disable = inet из main.cf. Когда все будет настроено и готово к запуску, данный параметр приводим к виду master_service_disable =
Конфигурирование
Конфиги дополнительного инстанса postfix-15
main.cf
compatibility_level = 2 queue_directory = /var/spool/postfix-15 command_directory = /usr/sbin daemon_directory = /usr/libexec/postfix data_directory = /var/lib/postfix-15 mail_owner = postfix myhostname = i15.mydomain.tld smtp_bind_address = x.x.x.15 smtp_helo_name = i15.mydomain.tld inet_interfaces = 192.168.55.15, x.x.x.15 inet_protocols = ipv4 smtp_use_tls = no mydestination = alias_maps = alias_database = local_recipient_maps = local_transport = error:5.1.1 Mailbox unavailable mynetworks = x.x.x.92, 192.168.55.0/24, 127.0.0.1 transport_maps = hash:/etc/postfix-15/transport slow15_destination_concurrency_limit = 8 slow15_destination_rate_delay = 0 slow15_destination_recipient_limit = 5 smtpd_banner = $myhostname ESMTP service ready multi_instance_enable = yes master_service_disable = authorized_submit_users = multi_instance_group = mailout multi_instance_name = postfix-15 unknown_local_recipient_reject_code = 550 debug_peer_level = 2 debugger_command = PATH=/bin:/usr/bin:/usr/local/bin:/usr/X11R6/bin ddd $daemon_directory/$process_name $process_id & sleep 5
master.cf
Сюда добавляем строку с именем сервиса slow15 (из main.cf)
slow15 unix - - n - - smtp -o syslog_name=postfix15/slow15
transport
Тут указываем домен mailhub.tld проблемного мейл-провайдера и имя сервиса из master.cf через который должна уходить почта
# MAILHUB.TLD mailhub.tld slow15:
После редактирования обязательно
postmap transport
Все. Дополнительный инстанс postfix-15 готов к запуску
postmulti -i postfix-15 -x postfix start
Аналогичным образом поднимается следующий дополнительный инстанс для пары адресов 192.168.55.16, x.x.x.16. Посмотреть статус запущеных инстансов можно командой:
postfix status
postfix/postfix-script: the Postfix mail system is running: PID: 4266
postfix-15/postfix-script: the Postfix mail system is running: PID: 19508
postfix-16/postfix-script: the Postfix mail system is running: PID: 20702
Видно, что запущены основной инстанс и два дополнительных
DNS
Нужно, чтоб dns-сервер умел работать в режиме round-robin. Такие как unbound и bind это умеют. У меня уже есть настроеный unbound в качестве форвардера, поэтому я раскомментирую строку rrset-roundrobin: yes в файле конфигурации unbound.conf
Еще нужно внести записи в прямую зону. До введения мультиинстанса для корректной работы достадочно было содержимого /etc/hosts. Однако postfix хочет наличия A-записей в прямой зоне, что более корректно, чем работа с /etc/hosts
В unbound.conf конфигурация для прямой зоны .local выглядит так:
local-zone: "local." static local-data: "mail.local. IN A 192.168.55.15" local-data: "mail.local. IN A 192.168.55.16"
Стоп-старт unbound
unbound-control stop unbound-control start
Теперь попеременный запуск команды ping mail.local должен вернуть ответы с 192.168.55.15 и 192.168.55.16. Если это так, то двигаемся дальше
Для дополнительных белых адресов, которые выдал нам провайдер необходимо внести изменения в обратную зону. Это необходимо для того, чтобы принимающие сервера не считали нас спамерами. Отправляем провайдеру следующую заявку:
Добрый день Просьба для следующих адресов внести изменения в обратной зоне x.x.x.15 IN PTR i15.mydomain.tld. x.x.x.16 IN PTR i16.mydomain.tld.
Изменения в прямой зоне делаем сами. Все это можно делать сразу после получения дополнительных адресов, до начала работ
Основной инстанс
До этого момента все действия описанные выше были относительно безопасными для работы мейлера. Перед тем как переключить отправку почты через дополнительные инстансы нужно иметь в рабочем состоянии следующее:
- Дополнительные белые адреса от провайдера и записи для них в прямой и обратной зоне. Работает обратный резолвинг
- Дополнительные адреса (белые и серые) висят на своих интерфейсах
- Сконфигурирован и запущен мультиинстанс postfix. Команда netstat -anl показывает интерфейсы 192.168.55.15:25 и 192.168.55.16:25 в состоянии LISTEN. Дополнительные инстансы готовы принимать почту от основного инстанса по серым адресам внутреннего интерфейса
- Сконфигурирован и корректно работает в режиме round-robin dns-сервер для внутренней зоны .local
Если по всем пунктам ответ утвердительный, то можно вносить изменения в конфигурацию основного инстанса. Переходим в папку /etc/postfix
master.cf
Сюда добавляем строку с именем сервиса slow
slow unix - - n - - smtp -o syslog_name=postfix/slow
transport
Тут указываем домен mailhub.tld, имя сервиса из master.cf и dns-имя мейлера из внутренней зоны через который должна уходить почта. Благодаря механизму round-robin это dns-имя всякий раз будет разное, почта пойдет через другой дополнительный инстанс и соединение с mailhub.tld состоится с другого белого адреса, что и нужно
# MAILHUB.TLD mailhub.tld slow:mail.local
После редактирования обязательно
postmap transport
Все. Самый ответственный момент
postfix reload
Перечитаны конфиги основного и дополнительных инстансов. В логах для mailhub.tld должны появиться похожие по смыслу записи:
Nov 22 13:43:54 i postfix/slow/smtp[12015]: 86E5862624: to=<nata@mailhub.tld>, relay=mail.local[192.168.55.15]:25, delay=0.28, delays=0.12/0.03/0.03/0.1, dsn=2.0.0, status=sent (250 2.0.0 Ok: queued as BCB0362648)
Nov 22 13:43:58 i postfix15/slow15/smtp[12019]: BCB0362648: to=<nata@mailhub.tld>, relay=mxs.mailhub.tld[z.z.z.z]:25, delay=3.6, delays=0.07/0.02/0.53/3, dsn=2.0.0, status=sent (250 OK id=1iY7Lw-000LVa-IO)
Nov 22 13:46:50 i postfix/slow/smtp[12015]: E658162749: to=<sfg@mailhub.tld>, relay=mail.local[192.168.55.16]:25, delay=0.23, delays=0.09/0/0.03/0.11, dsn=2.0.0, status=sent (250 2.0.0 Ok: queued as 1A2CD6276A)
Nov 22 13:46:53 i postfix16/slow16/smtp[12334]: 1A2CD6276A: to=<sfg@mailhub.tld>, relay=mxs.mailhub.tld[z.z.z.z]:25, delay=3.3, delays=0.09/0.03/0.58/2.6, dsn=2.0.0, status=sent (250 OK id=1iY7Ol-000BN0-Oe)
Остальная почта должна уходить как и раньше с основного инстанса
Управление инстансами
На примере инстанса postfix-15
postmulti -i postfix-15 -p postfix reload {start | stop} postmulti -i postfix-15 -x mailq postmulti -i postfix-15 -x postsuper -d ALL postmulti -i postfix-15 -x postsuper -d ALL deferred
Отключение и включение
postmulti -i postfix-15 -e disable postmulti -i postfix-15 -e enable
Отключение и удаление
postmulti -i postfix-15 -p stop
postmulti -i postfix-15 -e disable
postmulti -i postfix-15 -e destroy
Результаты
- Получена гибкая, масштабируемая система доставки писем разным мейл-провайдерам с smtp-ограничениями на входе
- Каждый инстанс конфигурируется отдельно под конкретные нужды
- Потребляемые ресурсы CPU/RAM выросли незначительно
- Усложнилось администрирование системы мультиинстанс postfix за счет наличия дополнительных очередей и конфигов
- Сложность администрирования мейлера осталась на прежнем уровне
Для сравнения графики «до» и «после»

Рассылка для 100К подписчиков. Слева почта уходит только через один инстанс, он же основной. Рассылка длится 4,5 часа. Справа — введено в эксплуатацию добавочно два дополнительных инстанса. Уже значительно легче. Рассылка ушла за 2 часа

В эксплуатации 13 дополнительных инстансов. Рассылки 100К слева и 200К+120К справа. Максимальная длительность рассылки до 2 часов каждая

- Системный администратор с 2000 года
- Участник Хабр Q&A и cyberforum
- Кейсы