АйТи Фреш
Главная / Статьи / Серверы и хостинг
Серверы и хостинг

Общий ящик не открывается: Dovecot и лимит mail_max_userip_connections

Автор: Семёнов Евгений Сергеевич, директор ООО «АйТи-Фреш» · · ~22 мин чтения
Общий ящик не открывается: Dovecot и лимит mail_max_userip_connections
Иллюстрация к статье «Общий ящик не открывается: Dovecot и лимит mail_max_userip_connections».

Ящик sales@ или info@ вдруг перестаёт открываться у части сотрудников. Пароль верный, вебмейл работает, сервер живой, у остальных всё в порядке. В 90 % случаев это не блокировка и не взлом, а упор в лимит одновременных IMAP-сеансов Dovecot. Разбираю, что именно считает сервер, почему первым ложится именно общий ящик, как это чинить по-взрослому и на что можно спокойно забить.

Симптом: «почта работает, а общий ящик не пускает»

Классический звонок в пятницу к вечеру: «У нас отвалилась почта». Начинаешь разбирать — отвалилась не почта. Личные ящики у всех открываются, вебмейл открывается, отправка идёт. Не открывается один конкретный ящик — общий: zakaz@, sales@, info@, buh@. И не у всех, а у двоих-троих. У тех, кто подключился последними. Через полчаса картина меняется: пустило этих, выпало других. Пользователи в этот момент рассказывают, что «сменили пароль», «заблокировали по IP» или «сервер перегружен». Ни одно из этих объяснений не верное.

Первое, что я делаю, — не лезу в настройки клиента, а иду в лог почтового сервера. На Debian/Ubuntu это обычно /var/log/mail.log, на RHEL-подобных /var/log/maillog, в контейнерных сборках — journald или лог контейнера. Нужна одна строка:

grep -F 'user+IP exceeded' /var/log/mail.log | tail -n 20

Если лимит тот самый, вы увидите примерно такое (в разных версиях перед текстом может стоять Disconnected:, а набор полей слегка отличаться):

dovecot: imap-login: Maximum number of connections from user+IP exceeded
  (mail_max_userip_connections=10): user=<zakaz@example.com>, method=PLAIN,
  rip=203.0.113.7, lip=192.168.10.25, TLS, session=<abcdEF123>

Дальше гадать не нужно — сообщение само себя объясняет. В скобках стоит имя параметра, который сработал. user= — логин, по которому идёт перебор лимита. rip= — remote IP, то есть адрес, с которого пришёл клиент (для офиса за NAT это будет один внешний адрес на всех). lip= — адрес самого сервера. method= — механизм аутентификации, TLS — сеанс шёл по шифрованному каналу: пароль при этом уже был принят, отказ случился после входа. Это не fail2ban, не политика паролей, не greylisting и не Rspamd. Это встроенный счётчик параллельных сеансов, и он отработал ровно так, как его настроили — точнее, как его оставили по умолчанию.

Отличать это надо ещё от соседней ошибки — «Maximum connection limit reached». Она про другое: про исчерпание client_limit/process_limit у сервиса imap или imap-login, то есть про потолок всего сервера, а не конкретного пользователя. Внешне похоже (клиент пишет «не удалось подключиться»), лечится совершенно иначе. Если в логе фигурирует user+IP — вы в моей статье по адресу.

Если в логе есть подстрока `mail_max_userip_connections` — прекращайте проверять пароли и сбрасывать профили Outlook. Причина найдена, дальше только арифметика.

Что Dovecot считает на самом деле: четыре пункта, которые всё меняют

Параметр называется mail_max_userip_connections, и в документации Dovecot CE он описан как «максимальное число IMAP-соединений, разрешённое пользователю с каждого IP-адреса». Значение по умолчанию — 10. Именно поэтому ошибка вылезает у всех одинаково: почти никто этот параметр не трогает, дефолт живёт в конфиге годами и до первого общего ящика никого не беспокоит.

Дальше начинаются нюансы, на которых системные администраторы регулярно спотыкаются. Разберу по пунктам, потому что каждый из них меняет диагноз.

Пункт первый и главный: считается пара «пользователь + IP», а не просто IP. То есть тридцать человек в офисе за одним NAT, у каждого свой ящик, — это тридцать независимых счётчиков по 10 соединений. Такая контора в лимит не упрётся никогда. А вот три человека, сидящие в одном ящике под одним логином с одного офисного адреса, — это один счётчик на троих. Вот вам и вся разница.

Пункт второй, неочевидный: имена пользователей сравниваются с учётом регистра. Zakaz@example.com и zakaz@example.com для счётчика — два разных пользователя. Кажется, что это подарок (лимит как бы удваивается), на практике это дыра в учёте: если у половины сотрудников логин записан с большой буквы, лимит начинает срабатывать непредсказуемо. Документация прямо говорит: чтобы это работало корректно, нормализация имени должна происходить уже на этапе passdb-поиска, а не в userdb. То есть приводить логин к нижнему регистру надо в аутентификации (auth_username_format, в ветке 2.4 значение по умолчанию — %{user | lower}, в 2.3 — %Lu; если у вас его переопределили, проверьте, что приведение к нижнему регистру осталось), а не позже. Правка в userdb делается слишком поздно — счётчик к этому моменту уже посчитал.

Пункт третий: проверка выполняется только на backend, прокси её не проверяют. Про это отдельный разговор ниже — там прячется самая мерзкая разновидность проблемы. И пункт четвёртый, бытовой: лимиты для IMAP и POP3 считаются отдельно, поэтому параметр обычно и кладут внутрь фильтра protocol imap { } — чтобы поднять его для IMAP и не трогать POP3.

Самая частая ошибка мышления: «у нас 40 человек за одним IP, вот и упёрлись в 10». Нет. Пока у каждого свой логин, у каждого свои 10. Проблема появляется ровно там, где несколько людей ходят под одной учёткой.
Общий ящик не открывается: Dovecot и лимит mail_max_userip_connections — схема
Схема к статье. Открыть схему в полном размере

Почему первым всегда ложится общий ящик

Дальше — простая арифметика, которую почти никто не делает заранее. Пользователи считают людей, а сервер считает TCP-сессии. Между этими числами разница в разы, и вот из чего она складывается.

Почтовые клиенты держат не одно соединение, а пул. Thunderbird по умолчанию кэширует до пяти соединений на аккаунт (настройка «Максимальное число кэшируемых соединений с сервером» в дополнительных параметрах сервера). Outlook в IMAP-режиме держит соединение на активную папку плюс отдельные под фоновую синхронизацию подписанных папок и под поиск — на большом ящике с десятком папок это спокойно 3–6 сессий. Мобильные клиенты держат по одной-две на аккаунт, но в режиме IDLE — то есть постоянно. Прибавьте, что у менеджера часто и ноутбук, и телефон.

Считаем реальную контору. Три менеджера в общем ящике: Thunderbird у одного (5 соединений), Outlook у двоих (по 4), у каждого телефон (по 1). Итого 5 + 8 + 3 = 16 при лимите 10. Ящик начинает пускать по принципу «кто раньше встал». А теперь вспомните, что в тот же ящик обычно ходят ещё и роботы: коннектор CRM (Битрикс24, Planfix), парсер заявок с сайта, imapsync-зеркало на резервный сервер, архиватор, антиспам-обучалка. Каждый — под тем же логином, часто с одного и того же сервера, то есть с одного rip. Три робота — минус три слота из десяти.

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

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

Разбор из практики: кондитерское производство «Сахарный завиток», 44 рабочих места

Производство кондитерских изделий «Сахарный завиток»: 44 рабочих места, из них в офисе — отдел продаж, логистика, бухгалтерия и технологи, остальные в цехе и на складе. Почта — собственный сервер на арендованной виртуальной машине: Postfix + Dovecot ветки 2.4, хранение в Maildir, доступ снаружи по IMAPS/993. Заказы от торговых сетей, кофеен и дилеров приходят на общий ящик zakaz@. Обращение звучало так: «Ящик заказов открывается через раз, у остальных всё нормально, а у нас предновогодний сезон и сети шлют заявки пачками». Первое предложение клиента, кстати, было «наверное, надо больше памяти серверу» — сервер при этом был загружен на 12 %.

Диагностика заняла минут пять. В логе — тот самый Maximum number of connections from user+IP exceeded (mail_max_userip_connections=10) с user=<zakaz@...>, и таких строк за сутки набралось около 1 400. Дальше живой срез:

# сводка по пользователям: колонка # — число соединений
doveadm who | sort -k2 -nr | head

# по строке на каждое соединение ящика заказов
doveadm who -1 'zakaz@example.com'

По ящику заказов стабильно 10 из 10, по остальным — от 1 до 4. Разложили, откуда набегает: шесть менеджеров отдела продаж под одним логином zakaz@ (Outlook — по 3–4 сессии), четыре телефона в IDLE, коннектор CRM, который по документации «проверял почту каждые две минуты», а по факту держал сессию открытой постоянно, и ночной imapsync на резервную площадку, который в сезон не всегда успевал завершиться до утра. Итого потребность — под 30 сессий при лимите 10.

Самое быстрое решение — поднять лимит до 50 и разойтись. Я так делать не стал, и вот почему: общий пароль в шести головах — это не проблема соединений, это проблема безопасности и учёта. Кто удалил письмо клиента — неизвестно. Уволился менеджер — надо менять пароль всем шестерым и перенастраивать четыре телефона. Поэтому сделали в два хода. Ход первый, за 20 минут: подняли лимит для IMAP до 30, чтобы снять боль немедленно и дать людям дожить сезон. Ход второй, за две недели: перевели общий ящик на нормальную схему — у каждого сотрудника свой логин, а zakaz@ подключён к ним как разделяемая папка через shared namespace и ACL. Роботов вынесли на отдельные технические учётки; imapsync передвинули на 03:40 и ограничили одним потоком.

Итог через три месяца: ни одной строки user+IP exceeded в логах. Пиковое число сессий на учётку — 6, лимит 30 остался как страховка и больше ни разу не подходил к потолку. Побочный эффект, ради которого стоило затевать: в логах теперь видно, кто из менеджеров и что делает с письмами клиента, а при увольнении достаточно отключить одну учётку. Честно скажу и про минус: перевод на shared-папки — это ручная перенастройка каждого клиента и полдня объяснений пользователям, что «ящик теперь вон в той ветке слева». Не бесплатно.

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

Как чинить: мой порядок приоритетов

Порядок именно такой, снизу вверх по трудозатратам и сверху вниз по правильности. Если времени в обрез — делайте пункты 1 и 2, остальное потом.

Пункт 1, немедленно (10–20 минут). Поднять лимит осознанно: посчитать реальную потребность по формуле «люди × устройства × 4 + роботы», округлить вверх и поставить. Не 10, не 1000, а посчитанное число с запасом процентов в 50.

# Dovecot 2.3: /etc/dovecot/conf.d/20-imap.conf
protocol imap {
  mail_max_userip_connections = 30
}

# Dovecot 2.3: /etc/dovecot/conf.d/20-pop3.conf
protocol pop3 {
  mail_max_userip_connections = 10
}

Применяем и обязательно проверяем, что сервер прочитал то, что вы написали:

doveconf -n | grep -B2 -A2 mail_max_userip_connections
doveadm reload

doveconf -n показывает итоговую конфигурацию после всех include — если правка попала в файл, который не подключается (а в панельных сборках вроде Plesk/ISPmanager это обычное дело), вы это увидите сразу.

Где именно лежит этот блок, зависит от ветки и сборки. В 2.3 из дистрибутивного пакета параметр уже присутствует закомментированным (#mail_max_userip_connections = 10) внутри protocol imap { } в conf.d/20-imap.conf и аналогично в 20-pop3.conf — достаточно раскомментировать и поменять число. В 2.4 все настройки глобальные, а protocol imap { } — это фильтр, который можно поставить в любом подключаемом файле; пакеты некоторых дистрибутивов по-прежнему раскладывают конфиг по conf.d, а официальный пример 2.4 — один компактный dovecot.conf. Если параметр задан и глобально, и внутри фильтра, для IMAP-сеансов побеждает значение из фильтра. В панелях (Plesk, ISPmanager, контейнерных сборках) правьте файл, который панель не перезаписывает при обновлении, — обычно это отдельный пользовательский include, и путь к нему смотрите в документации панели.

# Dovecot 2.4: dovecot.conf или любой подключаемый файл
protocol imap {
  mail_max_userip_connections = 30
}

Пункт 2, в ту же неделю. Развести роботов по отдельным техническим учётным записям. Коннектор CRM, imapsync, скрипт выгрузки в 1С — каждому свой логин с доступом к нужной папке через ACL. Это разгружает счётчик, но главное — когда робот сойдёт с ума и начнёт долбить сервер, он утопит только себя, а не живых людей.

Пункт 3, планово. Убрать общий логин как класс: личные учётки + разделяемая папка. Это единственный способ закрыть вопрос навсегда, заодно получить аудит и нормальное управление доступом. Пункт 4, по мелочи: прижать клиентов. В Thunderbird «Максимальное число кэшируемых соединений» с 5 до 2–3 — в 99 % случаев пользователь разницы не заметит, а слотов освободится заметно. В Outlook — отписаться от папок, которые никому не нужны.

А теперь на что можно забить. Не надо менять пароли — они ни при чём. Не надо гонять пользователей по NAT и покупать вторые внешние адреса «чтобы не считалось вместе» — если логины разные, они и так считаются раздельно. Не надо трогать fail2ban: он тут не участвует, и его настройки на эту ошибку не влияют. И не ставьте 0 в надежде на «безлимит» — документация такого поведения не обещает, а сюрприз в проде вам не нужен: ставьте конечное осмысленное число.

Задирать лимит в сотни — плохая идея. Каждый IMAP-сеанс это процесс или соединение внутри процесса; подняв лимит пользователя, вы просто переносите точку отказа на `process_limit` и `client_limit` сервиса imap, а там отказ выглядит куда неприятнее и валит уже всех.
Порядок действий: Как чинить: мой порядок приоритетов — схема
Порядок действий: Как чинить: мой порядок приоритетов. Открыть схему в полном размере

Диагностика: три команды, которые закрывают вопрос за минуту

Начинаю всегда с живого среза — кто сейчас висит на сервере и сколько сессий держит. doveadm who без ключей группирует соединения по пользователю: логин, число соединений (колонка #), протокол, список PID и адреса. С ключом -1 выводится по строке на каждое соединение — это удобно, когда нужно увидеть, с каких именно адресов пришли сессии:

# кто держит больше всех соединений (сводка по пользователям)
doveadm who | sort -k2 -nr | head -n 15

# конкретный ящик: по строке на соединение
doveadm who -1 'zakaz@example.com'

# все ящики домена
doveadm who '*@example.com'

# всё, что пришло из офисной сети за NAT
doveadm who -1 'zakaz@example.com' 203.0.113.7

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

Второй шаг — понять, это разовый всплеск или постоянный потолок. Смотрим лог за сутки и раскладываем отказы по пользователям:

grep -c 'user+IP exceeded' /var/log/mail.log

grep 'user+IP exceeded' /var/log/mail.log \
  | grep -o 'user=<[^>]*>' | sort | uniq -c | sort -rn | head

Десяток строк за неделю — можно не дёргаться, кто-то разово поднял пять клиентов. Полторы тысячи за сутки на один ящик, как у «Сахарного завитка», — это упор в потолок, и он не рассосётся.

Третий шаг, аварийный: сбросить залипшие сессии. doveadm kick отключает пользователей по маске имени и/или по IP:

# отключить все сессии конкретного ящика
doveadm kick 'zakaz@example.com'

# всё, что идёт с конкретного адреса
doveadm kick 203.0.113.7

Пользуйтесь этим аккуратно. Команда рвёт живые соединения: нормальный клиент переподключится сам и ничего не заметит, но Outlook в момент синхронизации большой папки может выдать пользователю ошибку и начать перекачивать заголовки заново. Я применяю kick только когда вижу зависшие сессии от давно ушедшего домой сотрудника или сбрендивший коннектор.

И маленький совет из практики: заведите на этот случай постоянный монитор. Одна строка в Zabbix (счётчик вхождений user+IP exceeded в маиллоге за 10 минут) с триггером на «больше пяти» — и в следующий раз вы узнаете о проблеме не от отдела продаж в пятницу вечером, а за неделю до того, как ящик начнёт отказывать регулярно.

Перед `doveadm kick` предупредите пользователей общего ящика. Одна оборванная синхронизация большого Outlook-профиля стоит вам получаса разговоров о том, что «после ваших работ почта сломалась».

Отдельная засада: прокси, фронтенды и переезд на 2.4

Вот тот пункт документации, который ломает диагностику сильнее всего: проверка mail_max_userip_connections выполняется только backend-серверами, прокси её не проверяют. Пока у вас один сервер, это неважно. Как только перед Dovecot появляется прослойка — Dovecot в режиме proxy, haproxy, балансировщик, TLS-терминатор, — начинаются чудеса.

Механика такая. Если прослойка не передаёт на backend реальный адрес клиента, то с точки зрения backend все соединения пользователя приходят с одного адреса — с адреса прокси. И лимит из «10 сессий на пользователя из каждой локации» превращается в «10 сессий на пользователя во всей вселенной». Компания с тремя офисами и общим ящиком в такой конфигурации ложится втрое быстрее, а в логе вы видите один и тот же rip= у всех, и это сбивает с толку: кажется, что кто-то один долбит сервер. Лечится это либо передачей реального IP (haproxy-протокол, доверенные сети в login_trusted_networks), либо честным расчётом лимита на всю популяцию сразу — но тогда вы теряете саму защиту от одного взбесившегося клиента.

Про версии. Актуальная ветка Dovecot CE — 2.4, ветка 2.3 уходит в разряд устаревших, и точный номер последнего релиза перед обновлением сверяйте со страницей релизов проекта. Переезд на 2.4 — история отдельная: конфигурация перестала быть иерархической, все настройки стали глобальными и применяются через фильтры (protocol, local, remote и другие). Вкладывать фильтры друг в друга можно, но не в произвольном сочетании: перед сложной вложенностью читайте раздел документации о фильтрах и проверяйте результат через doveconf -n — неверная конструкция либо не распарсится, либо молча применится не туда. Сам параметр mail_max_userip_connections в 2.4 не переименовали, дефолт остался 10, и protocol imap { } как фильтр для него работает.

Два подводных камня переезда, которые касаются нашей темы. Первый: в 2.4 соединения из login_trusted_networks должны быть зашифрованы (ssl = required) — если у вас прокси ходил на backend открытым текстом и через доверенную сеть подставлял реальные IP, после апгрейда эта схема перестанет работать, реальные адреса перестанут доезжать, и вы внезапно получите ровно ту картину, что описана абзацем выше. Второй: после любого апгрейда обязательно сверяйте doveconf -n до и после. У Dovecot есть онлайн-упгрейдер конфигов, но результат его работы всё равно надо читать глазами — молча потерянный protocol imap { } блок вернёт вам дефолтную десятку, и разбираться вы будете уже по звонкам пользователей.

После апгрейда 2.3 → 2.4 первым делом выполните `doveconf -n | grep mail_max_userip_connections`. Если строки нет — вы вернулись к дефолтным десяти и не знаете об этом.
Памятка: Отдельная засада: прокси, фронтенды и переезд на 2.4 — схема
Памятка: Отдельная засада: прокси, фронтенды и переезд на 2.4. Открыть схему в полном размере

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

Это блокировка за подбор пароля или атака?

Нет. Сообщение «Maximum number of connections from user+IP exceeded» выдаёт imap-login при исчерпании лимита одновременных сеансов, аутентификация при этом проходит успешно. Брутфорс в логах выглядит иначе — как серия auth failed с разными паролями. Менять пароль, разблокировать IP в fail2ban и перевыпускать сертификаты бессмысленно.

У нас 40 сотрудников за одним внешним IP. Надо ли поднимать лимит?

Если у каждого свой почтовый логин — не надо. Лимит считается на пару «пользователь + IP», поэтому 40 разных учёток за одним NAT дают 40 независимых счётчиков по 10 соединений. Поднимать лимит нужно только там, где несколько человек или роботов работают под одной учётной записью.

Можно просто поставить mail_max_userip_connections = 200 и забыть?

Технически можно, практически не советую. Лимит защищает сервер от одного сбойного клиента, который начнёт открывать сессии в цикле. При завышенном значении вы упрётесь в process_limit или client_limit сервиса imap, и тогда откажет не один ящик, а весь сервер. Считайте реальную потребность и ставьте её с запасом в 50 процентов, обычно это 20–40.

Чем эта ошибка отличается от «Maximum connection limit reached»?

Первая — про лимит конкретного пользователя с конкретного адреса (mail_max_userip_connections). Вторая — про исчерпание client_limit или process_limit сервиса imap/imap-login, то есть про потолок всего сервера. Симптом у пользователя похож, но во втором случае страдают все ящики сразу, и правится это в секции service, а не в protocol.

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

Дать каждому сотруднику личную учётную запись, а общий ящик подключить как разделяемую папку через shared namespace и ACL. Тогда каждый расходует собственный лимит, в логах видно, кто что сделал с письмом, а при увольнении отключается одна учётка вместо смены общего пароля на всех устройствах.

Лимит распространяется на POP3 и веб-почту?

Для POP3 лимит считается отдельно от IMAP, поэтому параметр обычно задают внутри фильтра protocol imap и при необходимости отдельно внутри protocol pop3. Веб-почта (SOGo, Roundcube) ходит на Dovecot по IMAP от имени пользователя, но со своего адреса — с адреса самого веб-сервера, поэтому её сессии считаются в отдельном счётчике и живые лимиты офиса обычно не затрагивают. Исключение — когда адрес веб-сервера внесён в login_trusted_networks и вебмейл передаёт Dovecot реальный IP пользователя: тогда сессии считаются от адреса сотрудника, а сам вебмейл с сотней пользователей может съесть лимит под одним логином, если он не переиспользует соединения.

Столкнулись с похожей задачей? Обращайтесь — решим

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

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

📞 +7 903 729-62-41 💬 MAX: +7 903 729-62-41 ✈ Telegram @ITfresh_Boss

С уважением, Семёнов Евгений Сергеевич, директор «АйТи Фреш» — IT-аутсорсинг для компаний до 50 рабочих мест, 15+ лет практики

Источники

© ООО «АйТи-Фреш» · Москва · Все статьи