Оригинал доступен на www.postfix.org

Обзор

В данной документации описываются признаки перегрузки SMTP-сервера Postfix. Он предоставляет постоянные изменения main.cf во избежание перегрузки во время работы в обычном режиме, и временные изменения main.cf для того, чтобы справиться с неожиданным выбросом почты. В этой документации содержатся конкретные предложения для Postfix 2.5 и более поздних версий, поддерживающих адаптивное поведение, а для более ранних версий Postfix — нет.

Темы, рассматриваемые в этой документации:

  • Признаки перегрузки SMTP-сервера Postfix
  • Автоматические меры при перегрузки
  • Обслуживайте больше клиентов SMTP одновременно
  • Тратьте меньше времени на SMTP-клиента
  • Отключите подозрительных SMTP-клиентов
  • Временные меры для старых версий Postfix
  • Обнаружение поддержки перегрузки
  • Включение или выключение адаптивного поведения при перегрузке
  • Другие меры по разгрузке зомби
  • Благодарность

Признаки перегрузки SMTP-сервера Postfix

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

Перегрузка SMTP-сервера может быть вызвана превышением допустимого объема почты (например: регистратор DNS открывает новую зону для регистрации), ошибкой (выход почты из строя, вызванный циклом пересылки) или ввиду злоумышленной деятельности (это может быть червь, бот или другие незаконные действия).

К признакам перегрузки SMTP-сервера Postfix относятся:

  • У удаленных SMTP-клиентов происходит значительная задержка, прежде чем Postfix отправит приветствие «220 hostname.example.com ESMTP Postfix».
    • ПРИМЕЧАНИЕ. Нерабочие конфигурации DNS также могут вызвать длительные задержки, прежде чем Postfix отправит «220 hostname.example.com…». Такие задержки также существуют, когда Postfix НЕ перегружен.
    • ПРИМЕЧАНИЕ. Чтобы конечным пользователям избежать «перегрузочных» задержек почтовых клиентов, включите запись службы «отправки» в cf (присутствует после Postfix 2.1) и попросите пользователей подключаться к ней вместо общедоступной службы SMTP.

 

  • SMTP-сервер Postfix регистрирует возросшее количество «потерянных соединений после СОЕДИНЕНИЯ». Так происходит потому, что удаленные SMTP-клиенты отключаются до того, как Postfix ответит на соединение.
    • ПРИМЕЧАНИЕ. Сканирование открытых SMTP-портов также может привести к сообщениям файла журнала типа «потерянное соединение…».
  • Postfix 2.3 и более поздние версии регистрируют предупреждение о том, что все порты сервера заняты:3 октября 20:39:27 spike postfix / master [28905]: предупреждение: служба «smtp»(25) достигла своего тех-предела «30»: новые клиенты могут испытывать заметные задержки
    3 октября 20:39:27 spike postfix / master [28905]: предупреждение: чтобы избежать этого увеличьте число процессов в master.cf или уменьшите время обслуживания каждого клиента
    3 октября 20:39:27 spike postfix / master [28905]: предупреждение: см. http://www.postfix.org/STRESS_README.html для ознакомления с примерами настроек конфигурации при перегрузке

Действительная почта, которая не доходит до адресата во время перегрузки SMTP-сервера Postfix, не обязательно теряется. Если условие перегрузки является временным, то она все равно должна прийти, как только ситуация вернется в нормальное состояние.

Автоматические меры при перегрузке

В версии Postfix 2.5 введено автоматическое принятие мер при перегрузке. Работает оно следующим образом. Когда «общедоступная» сетевая служба, такая как SMTP-сервер, переходит в состояние «все порты сервера заняты», демон Postfix master(8) регистрирует предупреждение, перезапускает службу (не прерывая существующие сетевые сеансы) и запускает службу с “-ostress = yes” в командной строке процесса сервера:

80821  ??  S      0:00.24 smtpd -n smtp -t inet -u -c -o stress=yes

Обычно демон Postfix master (8) запускает такой сервис с “-ostress =” в командной строке (то есть с пустым значением параметра):

83326  ??  S      0:00.28 smtpd -n smtp -t inet -u -c -o stress=

Вы не увидите параметры командной строки «-ostress» для сервисов, у которых имеются только локальные клиенты. Они включают службы, внутренние для Postfix (такие как администратор очередей) и службы, которые прослушивают только интерфейс с обратной связью (такие как службы SMTP после фильтрации)

Значение параметра “stress” является ключом к настройке параметра main.cf при перегрузке. Следующие настройки являются настройками по умолчанию в Postfix 2.6 и более поздних версиях.

1 smtpd_timeout = ${stress?{10}:{300}}s
2 smtpd_hard_error_limit = ${stress?{1}:{20}}
3 smtpd_junk_command_limit = ${stress?{1}:{100}}
4 # Parameters added after Postfix 2.6:
5 smtpd_per_record_deadline = ${stress?{yes}:{no}}
6 smtpd_starttls_timeout = ${stress?{10}:{300}}s
7 address_verify_poll_count = ${stress?{1}:{3}}

Версии Postfix до 3.0 используют более старую форму ${stress?x}${stress:y} вместо более новой формы ${stress?{x}:{y}}.

Синтаксис ${name?{value}:{value}}, ${name?value} и ${name:value} объясняется в начале справочной страницы postconf (5).

Объяснение:

  • Строка 1: в условиях перегрузки используйте значение smtpd_timeout 10 секунд вместо 300 секунд по умолчанию. Опыт работы со списком пользователей postfix от различных системных администраторов показывает, что сокращение «обычного» smtpd_timeout  до 60-ти вряд ли повлияет на настоящих клиентов. Однако вряд ли это станет настройкой Postfix по умолчанию, потому что такое не соответствует RFC. Установка smtpd_timeout на 10 или даже 5 секунд перегрузки все еще позволит большинству настоящих клиентов подключаться и отправлять почту, но может задержать почту от некоторых клиентов. Почта не должна быть потеряна, если эта мера используется только временно.
  • Строка 2: в условиях перегрузки, используйте smtpd_hard_error_limit вместо значения по умолчанию 20. Это отключает клиентов после одной ошибки, давая другим клиентам возможность подключения. Однако такое может привести к значительным задержкам с настоящей почтой, такой как список рассылки, который содержит несколько неактивных имен пользователей, которые не удосужились отписаться. Почта не должна быть потеряна, если эта мера используется только временно.
  • Строка 3: в условиях перегрузки используйте smtpd_junk_command_limit, равный 1, вместо значения по умолчанию 100. Это не позволяет клиентам держать соединения открытыми, повторно отправляя команды HELO, EHLO, NOOP, RSET, VRFY или ETRN.
  • Строка 5: в условиях перегрузки измените поведение smtpd_timeout  и smtpd_starttls_timeout, с ограничения по времени для системного вызова чтения или записи на ограничение по времени для отправки или получение полной записи (командная строка SMTP, строка ответа SMTP, сообщение SMTP строка содержимого или сообщение протокола TLS).
  • Строка 6: в условиях перегрузки сократите ограничение времени для приветственных сообщений протокола TLS с 300 секунд по умолчанию до 10 секунд. См. также обсуждение smtpd_timeout выше.
  • Строка 7: в условиях перегрузки не ждите до 6 секунд для завершения проверки адреса. Если результат еще не находится в кэше проверки адреса, немедленно ответьте с помощью $unverified_recipient_tempfail_action или $unverified_sender_tempfail_action. Почта не должна быть потеряна, если указанная мера используется только временно.

ПРИМЕЧАНИЕ. Имейте в виду, что функция адаптации к перегрузке — это довольно отчаянная мера, позволяющая поддерживать поток настоящей почты в условиях перегрузки. Если сайт достигает предела процесса SMTP-сервера, когда не происходит атака или поток ботов, то необходимо либо повысить предел процесса, либо добавить дополнительные средства техобеспечения.

Обслуживайте больше клиентов SMTP одновременно

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

Одной из мер, позволяющих избежать условия «все процессы сервера заняты», является одновременное обслуживание большего количества клиентов SMTP. Для этого вам нужно увеличить количество процессов SMTP-сервера Postfix. Данное решение улучшит скорость отклика для удаленных SMTP-клиентов, если на серверном компьютере имеется достаточно аппаратных и программных ресурсов для запуска дополнительных процессов и пока файловая система может справиться с дополнительной нагрузкой.

  • Вы можете увеличить количество процессов SMTP-сервера либо увеличивая default_process_limit в cf (строка 3 ниже), либо увеличивая поле «maxproc» SMTP-сервера в  master.cf (строка 10 ниже). В любом случае для того, чтобы изменения вступили в силу, вам нужно выполнить команду «postfix reload».
  • Пределы процесса свыше 1000 требуют использование версии Postfix 2.4 или еще новее, а также операционной системы, которая поддерживает фильтры событий на основе ядра (BSD kqueue(2), Linux epoll(4) или Solaris/dev/poll).
  • Большее количество процессов требует больше памяти. Вы можете уменьшить объем памяти Postfix, используя таблицы поиска cdb: вместо таблиц Berkeley DB hash: или btree:.

1 /etc/postfix/main.cf:
2        # Raise the global process limit, 100 since Postfix 2.0.
3          default_process_limit = 200
4
5 /etc/postfix/master.cf:
6  #=============================================================
7  # service type  private unpriv  chroot  wakeup  maxproc command
8  #==============================================================
9  # Raise the SMTP service process limit only.
10   smtp      inet  n       —       n       —       200     smtpd

  • ПРИМЕЧАНИЕ. Старые версии документа SMTPD_POLICY_README содержат ошибку: они настраивают фиксированное количество процессов демона. Когда вы поднимаете поле «maxproc» SMTP-сервера в cf, процессы SMTP-сервера будут сообщать о проблемах при подключении к алгоритмам распределения ресурсов сервера, потому что тех недостаточно. Примеры ошибок: «отказано в соединении» или «истекло время ожидания операции».Чтобы это исправить, отредактируйте cf и укажите нулевое поле “maxproc” во всех записях алгоритмов распределения сервера; см. строку 6 в примере, указанном ниже. Выполните команду “postfix reload”, чтобы изменения вступили в силу.

1 /etc/postfix/master.cf:
2     # =====================================================
3     # service type  private unpriv  chroot  wakeup  maxproc command
4     # =====================================================
5     # Disable the policy service process limit.
6     policy    unix  —       n       n       —       0       spawn
7         user=nobody argv=/some/where/policy-server

Тратьте меньше времени на SMTP-клиента

Если увеличение числа процессов SMTP-сервера являетсянецелесообразным, вы можете улучшить скорость отклика сервера Postfix, устранив задержки. Когда Postfix тратит меньше времени на сеанс SMTP, то же количество процессов SMTP-сервера может обслуживать больше клиентов за определенный промежуток времени.

  • Исключите нефункциональные списки RBL (блокированные списки, которые больше не работают). Подобный поиск может снизить производительность. Postfix регистрирует предупреждение тогда, когда сервер RBL не отвечает.
  • Исключите избыточные списки RBL (люди часто используют несколько списков Spamhaus RBL, включающие друг друга). Чтобы выяснить, включают ли RBL другие RBL, найдите сайты, где излагаются алгоритмы распределения ресурсов RBL.
  • Удалите header_checks и body_checks и оставьте только несколько шаблонов экстренных ситуаций, чтобы заблокировать последнее воздейсвие червя или рассылку. См. BACKSCATTER_README для примеров последнего.
  • Сгруппируйте шаблоны header_checks и body_checks, чтобы избежать ненужных операций сопоставления с шаблоном:

1  /etc/postfix/header_checks:
2      if /^Subject:/
3      /^Subject: virus found in mail from you/ reject
4      /^Subject: ..other../ reject
5      endif
6
7      if /^Received:/
8      /^Received: from (postfix\.org) / reject forged client name in received header: $1
9      /^Received: from ..other../ reject ….
10      endif

Отключите подозрительных SMTP-клиентов

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

  • Используйте коды ответов SMTP «521» (для Postfix 2.6 и более поздние версии) или «421» (для версий Postfix 2.3-2.5), чтобы закрыть линию для клиентов, которые соответствуют RBL, связанному с ботом (см. следующий пункт), или которые соответствуют выбранным ограничениям не-RBL, таким как карты доступа SMTP. SMTP-сервер Postfix будет отклонять почту и отключаться, не дожидаясь, пока удаленный SMTP-клиент отправит команду QUIT.
  • Чтобы перекрыть соединения от занесенных в черный список зомби, вы можете установить определенные коды отклонения SMTP-сервера Postfix для определенных RBL и для отдельных ответов от определенных RBL. Мы будем использовать zen.spamhaus.org в качестве примера; ко времени прочтения этой документации какие-то детали могут измениться. Прямо сейчас в их документации говорится, что ответ 127.0.0.10 или 127.0.0.11 указывает на динамический IP-адрес клиента, а это означает, что на компьютере, вероятно, запущен какой-то бот. Чтобы дать ответ 521 вместо ответа по умолчанию 554, используйте что-то вроде:

1  /etc/postfix/main.cf:
2      smtpd_client_restrictions =
3         permit_mynetworks
4         reject_rbl_client zen.spamhaus.org=127.0.0.10
5         reject_rbl_client zen.spamhaus.org=127.0.0.11
6         reject_rbl_client zen.spamhaus.org
7
8      rbl_reply_maps = hash:/etc/postfix/rbl_reply_maps
9
10  /etc/postfix/rbl_reply_maps:
11      # With Postfix 2.3-2.5 use «421» to hang up connections.
12      zen.spamhaus.org=127.0.0.10 521 4.7.1 Service unavailable;
13       $rbl_class [$rbl_what] blocked using
14       $rbl_domain${rbl_reason?; $rbl_reason}
15
16      zen.spamhaus.org=127.0.0.11 521 4.7.1 Service unavailable;
17       $rbl_class [$rbl_what] blocked using
18       $rbl_domain${rbl_reason?; $rbl_reason}

Хотя в приведенном выше примере показаны три поиска RBL (строки 4-6), Postfix будет выполнять только один DNS-запрос, поэтому он не влияет на производительность.

  • В версиях Postfix 2.3-2.5 используйте код ответа 421 (521 не приведет к отключению Postfix). Недостатком ответа с использованием кода 421 является то, что он работает только для зомби и других вредоносных программ. Если на клиенте запущен настоящий MTA, то он может подключиться снова несколько раз, пока не истечет срок действия почты в его очереди. Если проблема заключается в этом, то придерживайтесь ответа по умолчанию 554 и используйте «smtpd_hard_error_limit = 1», как описано ниже.
  • Вы можете автоматически включить вышеуказанную меру при перегрузке с помощью Postfix 2.5 и более поздних версий, либо же более ранних версий, которые содержат исправление исходного кода для адаптивного поведения при перегрузке с зеркал, перечисленных по адресу http://www.postfix.org/download.html. Просто замените строку выше 8 на:

8      rbl_reply_maps = ${stress?hash:/etc/postfix/rbl_reply_maps}

Более подробная информация об автоматической настройке при перегрузке находится в разделе «Автоматические меры при перегрузке».

Временные меры для старых версий Postfix

См. раздел «Автоматические меры при перегрузке», если вы используете Postfix версии 2.5 или новее, или же если вы применили патч исходного кода для адаптивного поведения при перезагрузке с зеркал, перечисленных по адресу http://www.postfix.org/download.html.

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

  • Уменьшите smtpd_timeout (по умолчанию: 300 секунд). Опыт работы со списком пользователей postfix от различных системных администраторов показывает, что сокращение «обычного» smtpd_timeout до 60-х вряд ли повлияет на законных клиентов. Однако вряд ли это станет Postfix по умолчанию, потому что он не соответствует RFC. Установка smtpd_timeout на 10 секунд (строка 2 ниже) или даже на 5 секунд в состоянии перегрузки все еще позволит большинству законных клиентов подключаться и отправлять почту, но может задержать почту от некоторых клиентов. Почта не должна быть потеряна, если эта мера используется только временно.
  • Уменьшите smtpd_hard_error_limit  (по умолчанию: 20). Установка этого значения на 1 в состоянии стресса (строка 3 ниже) помогает отключить клиентов после одной ошибки, давая другим клиентам возможность подключиться. Однако это может привести к значительным задержкам с настоящей почтой, такой как список рассылки, содержащий несколько неактивных имен пользователей, которые не удосужились отписаться. Почта не должна быть потеряна, если эта мера используется только временно.
  • Используйте smtpd_junk_command_limit, равный 1, вместо значения по умолчанию 100. Это препятствует тому, чтобы клиенты оставляли открытыми незанятые соединения, повторно отправляя команды NOOP или RSET.

1  /etc/postfix/main.cf:
2      smtpd_timeout = 10
3      smtpd_hard_error_limit = 1
4      smtpd_junk_command_limit = 1

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

Обнаружение поддержки перегрузки

Чтобы выяснить, поддерживает ли ваша установка Postfix адаптивное поведение при перегрузке, используйте команду «ps» и найдите процессы smtpd. У Postfix идет адаптивная поддержка при перегрузке, когда вы видите параметры командной строки «-o stress=» или «-o stress=yes». Помните, что при перегрузке Postfix никогда не допускает адаптивного поведения на серверах, которые прослушивают только локальные адреса.

Следующий пример предназначен для FreeBSD или Linux. В Solaris, HP-UX и других версиях System-V используйте «ps -ef» вместо  «ps ax».

$ ps ax | grep smtpd
83326 ?? S 0: 00,28 smtpd -n smtp -t inet -u -c -o стресс =
84345 ?? Ss 0: 00.11 / usr / bin / perl /usr/libexec/postfix/smtpd-policy.pl

Вы не можете использовать postconf(1) для определения адаптивной к стрессу поддержки. Команда postconf(1) игнорирует существование параметра стресса в  main.cf, потому что этот параметр там не действует. Настройки командной строки «-o параметр» всегда имеют приоритет над настройками параметров main.cf.

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

Включение или выключение адаптивного поведения при перегрузке

Вы можете вручную включить адаптивное поведение при перегрузке, добавив параметр командной строки «-o stress=yes» в master.cf. Это может быть полезно для тестирования переопределений в службе SMTP. Выполните «перезагрузку постфикса» для того, чтобы изменения вступили в силу.

Примечание: установка параметра стресса в  main.cf не влияет на сервисы, которые принимают удаленные соединения.

1 /etc/postfix/master.cf:
2     #=====================================================
3     # service type  private unpriv  chroot  wakeup  maxproc command
4     #=====================================================
5     #
6     smtp      inet  n       —       n       —       —       smtpd
7         -o stress=yes
8         -o . . .

Чтобы навсегда отключить адаптивное к перегрузке поведение с помощью определенной службы, укажите «-o stress=» в командной строке master.cf. Это может быть желательно для услуги «представления». Выполните «перезагрузку постфикса», чтобы изменения вступили в силу.

Примечание: установка параметра перегрузки в main.cf не влияет на сервисы, которые принимают удаленные соединения.

1 /etc/postfix/master.cf:
2     #=====================================================
3     # service type  private unpriv  chroot  wakeup  maxproc command
4     #======================================================
5     #
6     submission inet n       —       n       —       —       smtpd
7         -o stress=
8         -o . . .

Другие меры по разгрузке зомби

Демон postscreen(8), представленный в Postfix 2.8, обеспечивает дополнительную защиту от перегрузки почтового сервера. Один процесс postscreen(8) обрабатывает несколько входящих SMTP-соединений и решает, какие клиенты могут взаимодействовать с процессом SMTP-сервера Postfix. Удерживая спам-ботов, postscreen(8) оставляет больше процессов SMTP-сервера доступными для законных клиентов и задерживает наступление условий перегрузки сервера.

Благодарность

  • Спасибо членам списка рассылки postfix-users за то, что они поделились предшествующим опытом в сфере адаптации к перегрузке.
  • Спасибо за пример RBL и несколько других абзацев текста из сообщений пользователей Postfix, которые были адаптированы Ноэлом Джонсом.
  • Спасибо Витсе, который реализовал адаптивное к перегрузке поведение как наименьший возможный патч, в то время как он должен работать над другими вещами.