Отказоустойчивость DSPAM

EXIM, sendmail, postfix, Dovecot и прочие. Решение проблем связанных с работой электронной почты

Модератор: xM

Правила форума
Убедительная просьба юзать теги [code] при оформлении листингов.
Сообщения не оформленные должным образом имеют все шансы быть незамеченными.
Andrey12
рядовой
Сообщения: 12
Зарегистрирован: 2016-07-18 12:45:47

Отказоустойчивость DSPAM

Непрочитанное сообщение Andrey12 » 2016-07-18 14:08:34

Есть следующая схема маршрутизации входящей (извне) почты:
1) Пограничный почтовый релей на базе Exim
2) DSPAM-сервер (+ БД PostgreSQL на отдельном сервере; на этом же сервере поднят и exim, которому dspam передает почту, а exim в свою очередь передает ее на CAS - тут так же вопрос не является ли это немного избыточным и может стоит передавать сообщения сразу на CAS, а локальный exim убрать из этой связки)
3) Exchange CAS
4) Exchange MBX

Задача: обеспечить отказоустойчивость всех компонентов данной схемы. На данный момент при недоступности dspam'а письма остаются в очереди (defer) до восстановления работы dspam, но такой вариант не очень приемлем и нужно реализовать более полноценную схему.

Для элементов 1,3,4 обеспечить отказоустойчивость в принципе не проблема (1 - несколько серверов и соответственно MX записей, 3 - массив из CAS серверов, 4 - Exchnage DAG).
А вот с DSPAM не могу пока подобрать подходящую схему. На данный момент на пограничном релее (1) определен pipe-транспорт, который запускает клиент dspamc, который в свою очередь передает сообщения на DSPAM-сервер (2) (ServerMode dspam). Каких-либо опций, наподобие fallback_hosts как для smtp-транспорта, для pipe транспорта не нашел. Так же подумал передавать письма на dspam-сервер не с помощью клиента, а через smtp - в этом варианте в случае недоступности (наличия ошибок) dspam-сервера, можно было бы использовать параметр fallback_hosts и скажем передавать письма напрямую на CAS, но загвоздка в том, что насколько понял DSPAM-сервер может принимать сообщения только с использованием протокола LMTP, соответственно при определении которого в exim-транспорте не будет отрабатывать fallback_hosts, т.к. Exchange CAS не понимает LMTP (впрочем как и exim для входящих соединений).
Предполагаю несколько других вариантов отказоустойчивости:
1) Продублировать dspam-сервер, соответственно можно будет использовать fallback_hosts в транспорте smtp (с учетом протокола LMTP); так же сделать кластер из PostgreSQL. Тут так же вопрос корректно ли будут работать 2-а dspam-сервера с одной БД?
2) В соответствующем роутере на пограничном релее предусмотреть condition, в котором выполнять запуск скрипта, который будет проверять работоспособность (возможность приема сообщений) dspam-сервера

Соответственно вопрос: как вообщем обеспечить отказоустойчивость DSPAM'а, какие из вариантов более оптимальные, может стоит попробовать еще что-то?

Отправлено спустя 26 минут 10 секунд:
Еще как вариант рассматривается схема вообщем отказа от DSPAM и может даже Exim. Соответственно вопрос, что было бы оптимальнее, например, может тот же spamassasin?

Хостинговая компания Host-Food.ru
Хостинг HostFood.ru
 

Услуги хостинговой компании Host-Food.ru

Хостинг HostFood.ru

Тарифы на хостинг в России, от 12 рублей: https://www.host-food.ru/tariffs/hosting/
Тарифы на виртуальные сервера (VPS/VDS/KVM) в РФ, от 189 руб.: https://www.host-food.ru/tariffs/virtualny-server-vps/
Выделенные сервера, Россия, Москва, от 2000 рублей (HP Proliant G5, Intel Xeon E5430 (2.66GHz, Quad-Core, 12Mb), 8Gb RAM, 2x300Gb SAS HDD, P400i, 512Mb, BBU):
https://www.host-food.ru/tariffs/vydelennyi-server-ds/
Недорогие домены в популярных зонах: https://www.host-food.ru/domains/

Аватара пользователя
xM
ст. лейтенант
Сообщения: 1316
Зарегистрирован: 2009-01-15 23:57:41
Откуда: Königsberg
Контактная информация:

Отказоустойчивость DSPAM

Непрочитанное сообщение xM » 2016-07-18 15:07:28

Andrey12 писал(а): Задача: обеспечить отказоустойчивость всех компонентов данной схемы. На данный момент при недоступности dspam'а письма остаются в очереди (defer)
Если вызываете его из ACL, то / defer_ok и всё будет работать дальше без ожидания восстановления.
Но, и это главное, падать-то он не должен.

Стал читать дальше, и вижу что вызываете из транспорта (что правильнее).
Тогда читайте про опции роутера pass_router.
IT voodoo blog https://kostikov.co

Andrey12
рядовой
Сообщения: 12
Зарегистрирован: 2016-07-18 12:45:47

Отказоустойчивость DSPAM

Непрочитанное сообщение Andrey12 » 2016-07-18 15:19:04

xM писал(а):
Andrey12 писал(а): Задача: обеспечить отказоустойчивость всех компонентов данной схемы. На данный момент при недоступности dspam'а письма остаются в очереди (defer)
Если вызываете его из ACL, то / defer_ok и всё будет работать дальше без ожидания восстановления.
Но, и это главное, падать-то он не должен.
Вызов идет из транспорта (см. ниже), насколько понимаю тут так не получится? Можно ли вообще dspam корректно привязать к exim на уровне ACL?
Еще как вариант может в pipe-транспорте вызывать не dspamc, а скрипт который будет запускать dspamc и в случае определенных ошибок переотправлять письмо скажем непосредственно на CAS, или заново передавать exim'у с добавлением каких-то заголовков, чтобы письмо ушло на роутер, который передаст его на CAS-транспорт.

Код: Выделить всё

dspam_spamcheck_transport:
  driver = pipe
  debug_print = "T: dspam_spamcheck_transport for $local_part@$domain for dspam user ${lookup ldap {LDAP_AD_LOOKUP_LOGIN}{${lc:$value}}{DSPAM_NOLOGIN_USER}}"
  .ifdef LDAP_AD_LOOKUP_LOGIN
    .ifndef DSPAM_NOLOGIN_USER
       DSPAM_NOLOGIN_USER = dspam_no_login_user
    .endif
    command = /usr/bin/dspamc --user "${lookup ldap {LDAP_AD_LOOKUP_LOGIN}{${lc:$value}}{DSPAM_NOLOGIN_USER}}" \
                                --deliver=innocent -- $local_part@$domain
  .else
    command = /usr/bin/dspamc --user ${lc:$local_part@$domain} --deliver=innocent -- $local_part@$domain
  .endif
  user = dspam
  group = dspam
  log_output
  message_prefix =
  message_suffix =
  return_fail_output
  no_return_path_add
  temp_errors = *
.endif
Отправлено спустя 38 секунд:
xM писал(а): pass_router
Спасибо, почитаю.

Аватара пользователя
xM
ст. лейтенант
Сообщения: 1316
Зарегистрирован: 2009-01-15 23:57:41
Откуда: Königsberg
Контактная информация:

Отказоустойчивость DSPAM

Непрочитанное сообщение xM » 2016-07-18 15:42:20

Ну и потом не забудьте отписаться помогло ли.

Отправлено спустя 6 минут 40 секунд:
А не хотите попробовать убрать temp_errors и вставить вместо ignore_status = true?
IT voodoo blog https://kostikov.co

Andrey12
рядовой
Сообщения: 12
Зарегистрирован: 2016-07-18 12:45:47

Отказоустойчивость DSPAM

Непрочитанное сообщение Andrey12 » 2016-07-18 16:16:36

Попробовал добавить в роутер с dspam'ом параметр pass_router плюс с учетом (и без тоже) удаления в транспорте temp_errors и добавления ignore_status = true. Ничего не вышло. Ну и насколько понимаю ведь письмо уже прошло стадию роутинга и передано на обработку транспорту, соответственно опция pass_router уже не может как либо повлиять на дальнейшую обработку?
По поводу параметра temp_errors - он определялся для случаев, если что-то произошло с dspam-ом, то чтобы сообщения попадали в очередь, а не отклонялись с письмами рикошетами, соответственно при решении проблемы они из очереди доставлялись получателям. Установка же параметра ignore_status = true при наличии ошибки не ставит ни в очередь, ни в отклоняет с ошибкой (т.е. и рикошета тоже нет).
Падать dspam конечно не должен, да и работает в принципе стабильно, но это на случай более глобальных проблем, например, падение датацентра и т.п.

Код: Выделить всё

dspam_spamscan_router:
  debug_print = "R: dspam_spamscan_router for $local_part@$domain"
  driver = accept
  domains = +local_domains
  condition   = "${if and { \
                          {!def:acl_c_groups} \
                          {!def:acl_c_no_dspam} \
                          {!def:acl_m_no_dspam} \
                          {!def:h_X-FILTER-DSPAM:} \
                          {!eq {$received_protocol}{local}} \
                          { <= {$message_size}{3M}} \
                          }\
                          {1}{0}}"
  headers_add  = "X-FILTER-DSPAM: by $primary_hostname on $tod_full"
  transport = dspam_spamcheck_transport
  require_files = /usr/bin/dspamc
  address_test = false
  pass_router = manualroute_transport_additional
.endif

Аватара пользователя
xM
ст. лейтенант
Сообщения: 1316
Зарегистрирован: 2009-01-15 23:57:41
Откуда: Königsberg
Контактная информация:

Отказоустойчивость DSPAM

Непрочитанное сообщение xM » 2016-07-18 16:38:12

Andrey12 писал(а): Ну и насколько понимаю ведь письмо уже прошло стадию роутинга и передано на обработку транспорту, соответственно опция pass_router уже не может как либо повлиять на дальнейшую обработку?
Она меняет порядок обработки роутеров. Тут точно не поможет, стало понятно после того как вы транспорт опубликовали.
Andrey12 писал(а): Установка же параметра ignore_status = true при наличии ошибки не ставит ни в очередь, ни в отклоняет с ошибкой
Понятно. Спасибо за информацию, буду знать.

А я вот тогда не понял, поскольку с DSPAM не работал.
Вы отдаёте письмо серверу DSPAM. Ок. А дальше что с ним происходит?
Он должен его сам отправлять после обработки дальше как-то.
В случае со Spamassassin в конфигурации это явно видно:

Код: Выделить всё

root@beta:/home/xm # cat /usr/local/etc/exim/configure
# $Cambridge: exim/exim-src/src/configure.default,v 1.14 2009/10/16 07:46:13 tom Exp $
# --- by Max Kostikov (c) 2010...2016 v.20160618
...
spamd_address   = 127.0.0.1 783

# -- Spamassassin variables
SA_TIMEOUT      = 300s
SA_MAXSIZE      = 2097152
...

begin routers

# -- remote delivery
dnslookup:
...

domain_aliases:
...

user_aliases:
...

spamassassin_router:
  driver        = accept
  domains       = +local_domains
  transport     = spamassassin_local
  condition     = ${if and {{!eq{$received_protocol}{sa-checked}}\
                  {def:sender_host_address}\
                  {!match_ip{$sender_host_address}{+relay_from_hosts}}\
                  {!def:sender_host_authenticated}}{1}{0}}
  no_verify
  no_expn
...

local_user:
...

begin transports
...
spamassassin_local:
  driver                = pipe
  use_bsmtp             = true
  command               = /usr/local/sbin/exim -bS -oMr sa-checked
  transport_filter      = /usr/local/bin/spamc -s SA_MAXSIZE -u $local_part@$domain
  home_directory        = /tmp
  current_directory     = /tmp
  log_output            = true
  return_fail_output    = true
  return_path_add       = false
  timeout               = SA_TIMEOUT
  timeout_defer         = true
...
Вкратце, данный механизм отправляет на оценку демону Spamassassin данное письмо от пользователя с именем в формате полного почтового адреса через транспорт spamassassin_local который возвращает его на доставку в секцию роутеров с пометкой как принятой через псевдопротокол sa-checked, который роутер Spamassassin повторно уже не обрабатывает и производится уже локальная доставка через роутер local_user.
А у вас как-то этого механизма не видно, что несколько смущает.
IT voodoo blog https://kostikov.co

Andrey12
рядовой
Сообщения: 12
Зарегистрирован: 2016-07-18 12:45:47

Отказоустойчивость DSPAM

Непрочитанное сообщение Andrey12 » 2016-07-18 17:09:18

xM писал(а):
А я вот тогда не понял, поскольку с DSPAM не работал.
Вы отдаёте письмо серверу DSPAM. Ок. А дальше что с ним происходит?
Он должен его сам отправлять после обработки дальше как-то.
Опыта работы с DSPAM'ом у меня тоже не очень много, сейчас вот как бы и приобретаю.
Если кратко, после передачи письма клиентом dspamc на сервер (с учетом такой схемы работы), тот его обрабатывает и после проверки может отправить по SMTP или передать обратно на вход процессу exim (см. код ниже). Смотрю примеры конфигурации exim с dspam - есть в принципе аналогичные, что Вы указали в транспорте spamassassin_local. Что будет если spamassassin будет недоступен, например, проблемы с БД и т.п.?

Код: Выделить всё

TrustedDeliveryAgent "/usr/sbin/exim -oMr spam-scanned" # Exim

Аватара пользователя
xM
ст. лейтенант
Сообщения: 1316
Зарегистрирован: 2009-01-15 23:57:41
Откуда: Königsberg
Контактная информация:

Отказоустойчивость DSPAM

Непрочитанное сообщение xM » 2016-07-18 17:26:27

А, понятно. Т.е. уже сам DSPAM его вызывает. Спасибо.
В моём случае будет defer. Но за годы работы разных версий Spamassassin я что-то такого не припоминаю.
IT voodoo blog https://kostikov.co

Andrey12
рядовой
Сообщения: 12
Зарегистрирован: 2016-07-18 12:45:47

Отказоустойчивость DSPAM

Непрочитанное сообщение Andrey12 » 2016-07-18 19:11:22

Еще как вариант думаю, например, на уровне acl выполнять проверку доступности портов dspam-сервера и БД (скриптом или последовательностью нескольких команд), по результатам чего определять переменную, которую использовать как одно из условий в роутере dspam_spamscan_router - соответственно, если условие не будет выполняться, будет использоваться следующий роутер, который будет использовать транспорт с отправкой на CAS, а не на dspam-сервер. Тут же вопрос не слишком ли загрузят систему эти проверки (ясно нужно тестировать).

Аватара пользователя
xM
ст. лейтенант
Сообщения: 1316
Зарегистрирован: 2009-01-15 23:57:41
Откуда: Königsberg
Контактная информация:

Отказоустойчивость DSPAM

Непрочитанное сообщение xM » 2016-07-18 19:33:47

Andrey12 писал(а): Еще как вариант думаю, например, на уровне acl выполнять проверку доступности портов dspam-сервера
Здорово было бы если к нему можно было бы обращаться в ACL DATA как к, например, Spamassassin, через специальную команду.
Но такой возможности в штатном Exim нет. Есть патч от Виктора Устюгова, но его надо будет ручками накладывать.
Можно попробовать делать такую проверку через вызов cmdline.
IT voodoo blog https://kostikov.co

Andrey12
рядовой
Сообщения: 12
Зарегистрирован: 2016-07-18 12:45:47

Отказоустойчивость DSPAM

Непрочитанное сообщение Andrey12 » 2016-07-19 10:24:36

xM, спасибо посмотрю/попробую.

Andrey12
рядовой
Сообщения: 12
Зарегистрирован: 2016-07-18 12:45:47

Отказоустойчивость DSPAM

Непрочитанное сообщение Andrey12 » 2016-07-20 13:26:58

Придумал еще один вариант реализации. Использование проверки доступности порта на уровне роутера (внутри условий) при определении названия транспорта (один транспорт отправляет на dspam, а второй на CAS). Проверил отрабатывает корректно. На обработку каждого письма расходуется дополнительно ~20мс, думаю это не так уж и много.

Определение макросов (для удобства):

Код: Выделить всё

CHECK_DSPAM_COMMAND1 = /usr/bin/timeout 0.01s /bin/nc dspam.domain 2424 -z -w1
CHECK_DSPAM_COMMAND2 = /usr/bin/timeout 0.01s /bin/nc db.domain 5432 -z -w1
Правило в роутере:

Код: Выделить всё

 transport = ${if and { \
                       {eq {${run{CHECK_DSPAM_COMMAND1}{true}{false}}}{true}} \
                       {eq {${run{CHECK_DSPAM_COMMAND2}{true}{false}}}{true}} \
             }\
                       {dspam_spamcheck_transport}{remote_smtp_smarthost}\
             }

Аватара пользователя
xM
ст. лейтенант
Сообщения: 1316
Зарегистрирован: 2009-01-15 23:57:41
Откуда: Königsberg
Контактная информация:

Отказоустойчивость DSPAM

Непрочитанное сообщение xM » 2016-07-20 19:14:40

Ну да, как вариант. А время тут не сильно критично, конечно.
IT voodoo blog https://kostikov.co

Andrey12
рядовой
Сообщения: 12
Зарегистрирован: 2016-07-18 12:45:47

Отказоустойчивость DSPAM

Непрочитанное сообщение Andrey12 » 2016-07-21 18:24:05

Развернул exim на Debian 8 и обнаружил, что dspam'а больше нет в репах (в т.ч. и бекпортах) - то что развитие dspam фактически прекратилось еще в 2012 году знал, но так.. немного удивился (хотя конечно предсказуемо).
Начали рассматривать какую-то альтернативу dspam - может тот же spamassassin или rspamd. Одна из удобных особенностей для нашей среды была поддержка индивидуального пользовательского интерфейса в dspam, аутентификация по kerberos, поддержка клиент-серверной модели, не особая притязательность к ресурсам (хотя ночные задания обслуживания неплохо нагружали базу) - может кто-то что-то посоветует исходя из своего опыта?

Аватара пользователя
xM
ст. лейтенант
Сообщения: 1316
Зарегистрирован: 2009-01-15 23:57:41
Откуда: Königsberg
Контактная информация:

Отказоустойчивость DSPAM

Непрочитанное сообщение xM » 2016-07-21 21:38:22

Spamassassin всё это умеет. Единственный момент это то, что он на Perl. И хотя теперь он как-бы компилируется в бинарники, но скорость, конечно, ниже чем у написанных на C. Однако гибкость и всё такое у Spamassassin непревзойдённая.
Опять же Perl - бери и пиши свои модули сколько влезет.
IT voodoo blog https://kostikov.co

Andrey12
рядовой
Сообщения: 12
Зарегистрирован: 2016-07-18 12:45:47

Отказоустойчивость DSPAM

Непрочитанное сообщение Andrey12 » 2016-07-29 13:15:17

xM, не подскажите какой-то веб-интерфейс для SA?
Основные требования (в порядке важности):
1) индивидуальные пользовательские настройки
2) аутентификация доменных (AD) пользователей
3) русский интерфейс
4) поддержка карантина

Установил webuserprefs - не очень подходит, т.к. нет русского интерфейса, аутентификация выполняется через IMAP и т.п., а не по NTLM/Kerberos, нет карантина. Судя по скриншотам у php-sa-mysql функционал в принципе аналогичен.

Аватара пользователя
xM
ст. лейтенант
Сообщения: 1316
Зарегистрирован: 2009-01-15 23:57:41
Откуда: Königsberg
Контактная информация:

Отказоустойчивость DSPAM

Непрочитанное сообщение xM » 2016-07-29 15:01:21

Andrey12 писал(а): xM, не подскажите какой-то веб-интерфейс для SA?
Эээ... А он нужен вообще? Ни разу за годы работы такой потребности не возникало.
По пользовательским настройкам есть плагин для Roundcube SAUserPrefs, который является у нас основным корпоративным клиентом. Однако, на практике им никто не пользуется, поскольку SA на автомате и с помощью механизма пользовательского контроля (плагин MarkAsJunk2 + отложенное пакетное обучение) прекрасно справляется со своими обязанностями.
IT voodoo blog https://kostikov.co

Andrey12
рядовой
Сообщения: 12
Зарегистрирован: 2016-07-18 12:45:47

Отказоустойчивость DSPAM

Непрочитанное сообщение Andrey12 » 2016-08-02 18:20:26

Спасибо, возьму на заметку.
И еще момент по поводу недоступности SA. Установил в тестовой среде на отдельном сервере и вижу (конфигурация в принципе аналогична Вашей, но без Timeout'ов), что при его недоступности письмо просто передается далее без проверки - т.е. spamc (в transport_filter) возвращает то же письмо в command, но без заголовков SA. Т.е. defer по факту не происходит (насколько понимаю происходит только при таймауте.). Соответственно не нужно ничего мудрить с отказоустойчивостью. Для того чтобы мониторить такие ситуации сделал отдельный роутер, который передает письма на smarthost в случает отсутствия проверок SA (плюс доп. условия) - соответственно будет периодически мониторится лог на вхождение названия этого роутера.

Аватара пользователя
xM
ст. лейтенант
Сообщения: 1316
Зарегистрирован: 2009-01-15 23:57:41
Откуда: Königsberg
Контактная информация:

Отказоустойчивость DSPAM

Непрочитанное сообщение xM » 2016-08-03 13:21:07

Andrey12 писал(а): Т.е. defer по факту не происходит
Да, если что-то типа connection refused то не происходит. Но в транспортах, насколько я помню, есть механизм мониторинга ошибок через STDERR.
IT voodoo blog https://kostikov.co