Очередь Postfix в Zimbra растёт: amavis, ClamAV и resolv.conf

Автосервис в Одинцово, 14 рабочих мест, март 2023 года. Клиенты жаловались, что счета приходят через полчаса после звонка, а часть писем не доходила вовсе. В очереди висело 1 248 сообщений. Я сначала пошёл по ложному следу — про чёрные списки, — а потом набрал одну команду, которая за минуту отрезала половину гипотез.

«Мы отправили полчаса назад» — а письмо ещё не пришло

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

Потом появляется вторая часть жалобы. Часть писем не доходит вообще, а через 5 суток отправителю падает уведомление о недоставке — по адресам, которые точно рабочие.

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

Есть команда, которая за минуту отсекает две из четырёх. Называется qshape. Расскажу про неё на конкретном случае — и заодно про то, как я в этом же случае удалил 60 писем, которые ещё могли доехать.

Одинцово, март 2023: 1 248 писем в очереди

Автосервис на Красногорском шоссе, 14 рабочих мест: приёмка, два мастера-консультанта, склад запчастей, бухгалтерия. Zimbra 9.0.0 Open Source на Ubuntu 20.04, поставлена в 2021 году, около сорока гигабайт почты. Обслуживает их приходящий человек, который сам честно сказал: «я в почте не разбираюсь, я по компьютерам».

Жалоба на входе была ровно такая, как выше. Счета уходят к клиентам с задержкой, заявки от корпоративных заказчиков теряются, часть писем через несколько суток возвращается с ошибкой доставки.

Первое, что я сделал, — посмотрел размер очереди:

[zimbra@mail ~]$ zmqstat
deferred=1248
incoming=0
active=43
hold=0
corrupt=0

1 248 отложенных писем на контору из 14 человек. Это очередь, которая копится не первый день: задержки тут замечали и раньше, но массовыми жалобы стали с конца февраля, недели за три до звонка. И 43 штуки в активной: они прямо сейчас в обработке и не могут её закончить.

Сорок три в active — самая говорящая цифра из трёх. Активная очередь на маленьком сервере должна быть пустой почти всегда: письмо туда попадает на секунды. Если там постоянно висит несколько десятков — значит, обработка каждого письма занимает минуты, а не секунды. И искать надо не снаружи, а внутри цепочки обработки.

Ложная версия: «нас внесли в чёрные списки»

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

Версия проверяемая, и я потратил на неё 40 минут. Проверил адрес по десятку RBL — чисто. Посмотрел PTR — на месте, совпадает с именем сервера. Записи SPF и DKIM валидные, подпись проходит. Ни одного повода для блокировки.

А потом набрал команду, с которой надо было начать:

[zimbra@mail ~]$ qshape deferred | head -12
                        T  5 10 20 40 80 160 320 640 1280 1280+
              TOTAL   1248 18 34 61 122 178 246  297  212   80
    mail.ru              216  3  6 11  22  31  42   52   37   12
    yandex.ru            186  2  5  9  18  27  38   43   32   12
    gmail.com             97  1  3  5  10  14  19   23   17    5
    autoservice.local     94  2  4  7  11  13  18   21   14    4
    partner-detali.ru     71  1  2  4   7  10  14   17   12    4
    ...

Вот здесь версия про чёрные списки умерла. Очередь размазана ровным слоем по всем доменам пропорционально их доле в переписке — включая autoservice.local, то есть письма между своими же сотрудниками, которые вообще не покидают сервер. Девяносто четыре внутренних письма не могут висеть из-за чужого чёрного списка (autoservice.local — их внутренняя зона, наружу контора пишет с autoservice.ru). Значит, узкое место у нас.

Команда qshape — самый недооценённый инструмент в этой истории. Она рисует форму очереди: строки — домены получателей, столбцы — возраст писем в минутах. Читается она так:

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

Четыре причины, дающие один и тот же симптом

Когда стало ясно, что дело внутри, круг сузился до четырёх вариантов. Все четыре выглядят снаружи одинаково. Письма стоят, потом медленно уходят.

Подвисший антивирусный фильтр

Письмо в Zimbra не летит от отправителя к получателю напрямую. Маршрут такой: клиент сдаёт письмо на 25 или 587, дальше внутренняя обработка и планировщик, затем письмо уходит на 127.0.0.1:10024 службе amavisd, та зовёт ClamAV и SpamAssassin, и возвращает письмо обратно на порт 10025 — для окончательной раскладки в ящик по LMTP на 7025.

Точка отказа тут одна. Порт 10024.

В настройках транспорта smtp-amavis заложен таймаут 20 минут и параметр max_use=20: после двадцати писем экземпляр перезапускается. Если amavisd отвечает медленно, письмо застревает ровно посередине маршрута и висит эти самые двадцать минут. Отсюда и берутся жалобы «пришло через полчаса». Смотреть надо в /opt/zimbra/log/amavis.log и на вывод zmamavisdctl status.

Просроченный ClamAV

Частный и самый противный случай предыдущего пункта. Движок с устаревшими базами или устаревшей версией начинает отдавать ошибку вместо вердикта, и amavisd честно откладывает письмо, вместо того чтобы пропустить его непроверенным. Встаёт всё сразу: входящая, исходящая, внутренняя. Проверяется одним листингом /opt/zimbra/data/clamav/db/ — по датам файлов main.cvd и daily.cvd.

Битый /etc/resolv.conf

Служба доставки для каждого письма выясняет, куда его нести, и делает это через DNS. Если в /etc/resolv.conf указан адрес, который молчит, каждое письмо оплачивает свою порцию таймаута — обычно 5 секунд на попытку, и попыток две. Симптом описывают одинаково: письма зависают в активной очереди на 15–20 минут. Сервер при этом абсолютно исправен. Ни одной ошибки в логах.

Разъехавшийся DNS изнутри и снаружи

Когда внутренние клиенты и внешний мир видят разные адреса одного имени, почта уходит наружу через периметр и пытается вернуться обратно тем же путём. Получается петля. Письма копятся сотнями по таймауту, и в qshape deferred видно много записей на собственные домены компании. Лечится настройкой раздельного DNS для внутренней зоны, а не правкой почтового сервера.

Проверьте у себя за две минуты

Четыре команды. Все безопасные, ничего не меняют, выполняются под пользователем zimbra.

# размер и форма очереди
zmqstat
qshape deferred | head -12
qshape active | head -8

# жив ли антивирусно-антиспамовый фильтр
zmamavisdctl status
tail -30 /opt/zimbra/log/amavis.log

# насколько свежие вирусные базы
ls -l --time-style=long-iso /opt/zimbra/data/clamav/db/

# кому сервер задаёт вопросы про имена
cat /etc/resolv.conf
Что увиделиЧто это значитНасколько срочно
В active висит больше десятка писем постоянноОбработка одного письма занимает минуты. Узкое место внутри сервераСегодня
В qshape deferred резко выделяется один доменПроблема на стороне получателя, ваш сервер здоровНа неделе
Очередь размазана ровно, есть свои доменыПроблема у вас: фильтр, антивирус или разрешение имёнСегодня
Файлам вирусных баз больше месяцаОбновления не приходят. Скоро встанет вся почтаСегодня
В resolv.conf адрес, который не отвечает на запросыКаждое письмо оплачивает таймаут ожиданияПрямо сейчас, это правка на минуту
Много писем в столбцах справаОни лежат больше суток. Через пять суток вернутся отправителямСегодня, потом будет поздно

Про последнюю строку: срок жизни письма в очереди по умолчанию — пять суток. Всё это время сервер повторяет попытки с нарастающими паузами, а по истечении срока возвращает письмо отправителю с уведомлением о недоставке. Пять суток — это ваш запас времени. Не больше.

Что нашлось: антивирус с базами позапрошлого года

Проверка заняла три минуты и дала сразу два попадания.

[zimbra@mail ~]$ ls -l --time-style=long-iso /opt/zimbra/data/clamav/db/
-rw-r--r-- 1 zimbra zimbra 170868224 2021-11-08 04:12 main.cvd
-rw-r--r-- 1 zimbra zimbra 132096512 2021-11-09 04:15 daily.cvd
-rw-r--r-- 1 zimbra zimbra    294912 2021-11-08 04:12 bytecode.cvd

[zimbra@mail ~]$ tail -6 /opt/zimbra/log/freshclam.log
ERROR: Can't download daily.cvd from database.clamav.net
WARNING: Your ClamAV installation is OUTDATED!
WARNING: Local version: 0.103.2 Recommended version: 0.103.8

[zimbra@mail ~]$ tail -4 /opt/zimbra/log/amavis.log
(!)ClamAV-clamd av-scanner FAILED: run_av error: timed out
(!)WARN: all primary virus scanners failed, considering backups
TIMING [total 1204 ms] ... SMTP pre-DATA-flush 0, DATA 1180

Базы от ноября 2021 года. Обновление перестало приходить полтора года назад — сервер сидел за роутером, где кто-то закрыл исходящие соединения «для безопасности», и служба обновления с тех пор молча падала в лог, который никто не читал.

Второе попадание — файл настроек разрешения имён:

[zimbra@mail ~]$ cat /etc/resolv.conf
nameserver 192.168.88.1
nameserver 213.xxx.xxx.4
search local

Первый адрес — роутер, живой. Второй — сервер имён прежнего провайдера, которого автосервис сменил осенью 2022 года. Он не отвечал ничем: ни отказом, ни ошибкой. Просто тишина до истечения таймаута. И на каждое письмо, где первый адрес не успевал ответить, накидывалось ожидание.

Обе причины работали одновременно. И усиливали друг друга: ClamAV отдавал вердикт с задержкой, amavisd держал соединение на 10024, qmgr ждал своё, а мёртвый resolver добавлял сверху собственные секунды на каждом письме.

Моя ошибка: шестьдесят писем, которые ещё могли доехать

Я починил обе причины за 1 час 20 минут. Открыл на роутере исходящие 443 и 53 для freshclam, дождался свежих daily.cvd, перезапустил amavisd через zmamavisdctl restart, вычистил мёртвый адрес из /etc/resolv.conf.

А потом сделал глупость. Очередь на 1 248 писем меня раздражала: она мешала смотреть, начали ли новые письма проходить нормально. И я по инерции набрал команду очистки отложенного. Секундное движение.

# то, что делать не следовало
postsuper -d ALL deferred
# postsuper: Deleted: 1248 messages

Правильный порядок был другой: сначала форсировать доставку всего, что накопилось, и только потом — при необходимости — чистить остаток.

# как надо было
postqueue -f              # немедленная попытка доставить всё отложенное
sleep 300
zmqstat                   # смотрим, что осталось
qshape deferred | head     # и почему именно оно осталось

Из тех 1 248 писем большая часть была мусором — повторы, автоматические уведомления, рассылки. Но около шестидесяти были живыми письмами возрастом меньше пяти суток: они бы доехали за первые же минуты после починки. Мы восстановили из них сорок одно — из папки «Отправленные» у самих сотрудников и из ящиков контрагентов. Остальные девятнадцать я просто потерял.

Вывод, который я с тех пор держу в голове как правило: очередь — это не мусор, это письма ваших клиентов. Удалять её можно только после того, как принудительная доставка прошла и вы посмотрели, что именно осталось лежать и почему. Команда postsuper -d ALL deferred сносит именно отложенные, аккуратнее общего варианта — но живые письма она сносит точно так же.

Тюнинг очереди: только через локальную конфигурацию

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

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

# так правки переживут перезапуск и обновление
zmlocalconfig -e postfix_queue_run_delay=180s
zmlocalconfig -e postfix_minimal_backoff_time=180s
zmlocalconfig -e postfix_maximal_backoff_time=1800s

# применить
zmmtaconfig
# или, если хочется наверняка
zmcontrol restart

# проверить, что значение реально встало
zmlocalconfig -s postfix_queue_run_delay

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

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

Итог и где это перестаёт быть часовой работой

Цифры по Одинцово.

  • Диагностика: 40 минут по ложному следу плюс 6 минут на четыре правильные команды.
  • Починка: 1 час 20 минут, из них час — ожидание, пока скачаются свежие вирусные базы объёмом около 300 мегабайт.
  • Задержка доставки после починки: с 15–20 минут до 4–9 секунд.
  • Активная очередь: с 43 писем до нуля.
  • Потеряно по моей вине: 19 писем из 1 248.
  • Счёт клиенту: 12 000 рублей.
  • Сколько это тянулось до звонка мне: полтора года в мягкой форме и три недели в острой.

Цена бездействия здесь считается не через простой. Через недополученные заказы. Владелец посчитал по своей учётной системе: за три острые недели сорвалось 11 согласований на запчасти, где ответ клиента ждали в тот же день. Средний чек по таким заявкам — около 22 000 рублей. Даже если сорвалась половина, это шестизначная сумма против счёта в 12 000.

Где ломается самостоятельная попытка

Последовательность я расписал целиком, и она несложная. Ломается обычно не она.

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

Второе. Причины любят ходить парами. Починив ClamAV, вы увидите улучшение: задержка упадёт с 20 минут до 3. И решите, что справились. А 3 минуты вместо 4 секунд — это по-прежнему мёртвый адрес в /etc/resolv.conf, просто теперь он не так заметен.

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

Четвёртое. Просроченный антивирус в цепочке почты — это не только задержки. Полтора года почта автосервиса проверялась базами позапрошлого года, то есть фактически не проверялась. Это отдельный разговор, и он про безопасность, а не про очередь.

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

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

Можно ли просто отключить антивирусную проверку, чтобы почта пошла?

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

Почему письма между своими же сотрудниками тоже висят в очереди?

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

Что будет с письмами, которые уже несколько дней лежат в очереди?

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

Мы правили main.cf руками, и всё работало. Почему нельзя?

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

Как понять, что причина в разрешении имён, а не в фильтре?

Есть простая проверка: замерить время ответа каждого сервера имён из списка. Возьмите любую утилиту опроса и обратитесь к каждому адресу по очереди, засекая время. Живой сервер отвечает за десятки миллисекунд, мёртвый — не отвечает вовсе и утилита сама сообщит о таймауте. Второй признак: если задержка составляет ровно круглые величины — пять секунд, десять, — это почти всегда таймаут, а не медленная работа. Настоящая перегрузка даёт разброс, а таймаут срабатывает по расписанию, всегда одинаково.

Нужна помощь с проектом?

Специалисты АйТи Фреш помогут с архитектурой, DevOps, безопасностью и разработкой — 15+ лет опыта

📞 Связаться с нами
#Zimbra#Postfix#amavis#ClamAV#доставка почты
Комментарии 0

Оставить комментарий

загрузка...

Подпишитесь на рассылку ITfresh

Раз в неделю — практические гайды для руководителя IT и сисадмина: безопасность, 1С, миграции, резервные копии, лайфхаки из реальных проектов.

Реквизиты оператора персональных данных

ООО «АЙТИ-ФРЕШ», ИНН 7719418495, КПП 771901001. Юридический адрес: 105523, г. Москва, Щёлковское шоссе, д. 92, корп. 7. Контакт: info@itfresh.ru, +7 903 729-62-41. Оператор обрабатывает e-mail подписчика в целях рассылки информационных и рекламных материалов до момента отзыва согласия.