Страница 1 из 1
Отказоустойчивость DSPAM
Добавлено: 2016-07-18 14:08:34
Andrey12
Есть следующая схема маршрутизации входящей (извне) почты:
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?
Отказоустойчивость DSPAM
Добавлено: 2016-07-18 15:07:28
xM
Andrey12 писал(а): Задача: обеспечить отказоустойчивость всех компонентов данной схемы. На данный момент при недоступности dspam'а письма остаются в очереди (defer)
Если вызываете его из ACL, то
/ defer_ok и всё будет работать дальше без ожидания восстановления.
Но, и это главное, падать-то он не должен.
Стал читать дальше, и вижу что вызываете из транспорта (что правильнее).
Тогда читайте про опции роутера
pass_router.
Отказоустойчивость DSPAM
Добавлено: 2016-07-18 15:19:04
Andrey12
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 секунд:
Спасибо, почитаю.
Отказоустойчивость DSPAM
Добавлено: 2016-07-18 15:42:20
xM
Ну и потом не забудьте отписаться помогло ли.
Отправлено спустя 6 минут 40 секунд:
А не хотите попробовать убрать temp_errors и вставить вместо ignore_status = true?
Отказоустойчивость DSPAM
Добавлено: 2016-07-18 16:16:36
Andrey12
Попробовал добавить в роутер с 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
Отказоустойчивость DSPAM
Добавлено: 2016-07-18 16:38:12
xM
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.
А у вас как-то этого механизма не видно, что несколько смущает.
Отказоустойчивость DSPAM
Добавлено: 2016-07-18 17:09:18
Andrey12
xM писал(а):
А я вот тогда не понял, поскольку с DSPAM не работал.
Вы отдаёте письмо серверу DSPAM. Ок. А дальше что с ним происходит?
Он должен его сам отправлять после обработки дальше как-то.
Опыта работы с DSPAM'ом у меня тоже не очень много, сейчас вот как бы и приобретаю.
Если кратко, после передачи письма клиентом dspamc на сервер (с учетом такой схемы работы), тот его обрабатывает и после проверки может отправить по SMTP или передать обратно на вход процессу exim (см. код ниже). Смотрю примеры конфигурации exim с dspam - есть в принципе аналогичные, что Вы указали в транспорте spamassassin_local. Что будет если spamassassin будет недоступен, например, проблемы с БД и т.п.?
Код: Выделить всё
TrustedDeliveryAgent "/usr/sbin/exim -oMr spam-scanned" # Exim
Отказоустойчивость DSPAM
Добавлено: 2016-07-18 17:26:27
xM
А, понятно. Т.е. уже сам DSPAM его вызывает. Спасибо.
В моём случае будет defer. Но за годы работы разных версий Spamassassin я что-то такого не припоминаю.
Отказоустойчивость DSPAM
Добавлено: 2016-07-18 19:11:22
Andrey12
Еще как вариант думаю, например, на уровне acl выполнять проверку доступности портов dspam-сервера и БД (скриптом или последовательностью нескольких команд), по результатам чего определять переменную, которую использовать как одно из условий в роутере dspam_spamscan_router - соответственно, если условие не будет выполняться, будет использоваться следующий роутер, который будет использовать транспорт с отправкой на CAS, а не на dspam-сервер. Тут же вопрос не слишком ли загрузят систему эти проверки (ясно нужно тестировать).
Отказоустойчивость DSPAM
Добавлено: 2016-07-18 19:33:47
xM
Andrey12 писал(а): Еще как вариант думаю, например, на уровне acl выполнять проверку доступности портов dspam-сервера
Здорово было бы если к нему можно было бы обращаться в ACL DATA как к, например, Spamassassin, через специальную команду.
Но такой возможности в штатном Exim нет. Есть патч от
Виктора Устюгова, но его надо будет ручками накладывать.
Можно попробовать делать такую проверку через вызов
cmdline.
Отказоустойчивость DSPAM
Добавлено: 2016-07-19 10:24:36
Andrey12
xM, спасибо посмотрю/попробую.
Отказоустойчивость DSPAM
Добавлено: 2016-07-20 13:26:58
Andrey12
Придумал еще один вариант реализации. Использование проверки доступности порта на уровне роутера (внутри условий) при определении названия транспорта (один транспорт отправляет на 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}\
}
Отказоустойчивость DSPAM
Добавлено: 2016-07-20 19:14:40
xM
Ну да, как вариант. А время тут не сильно критично, конечно.
Отказоустойчивость DSPAM
Добавлено: 2016-07-21 18:24:05
Andrey12
Развернул exim на Debian 8 и обнаружил, что dspam'а больше нет в репах (в т.ч. и бекпортах) - то что развитие dspam фактически прекратилось еще в 2012 году знал, но так.. немного удивился (хотя конечно предсказуемо).
Начали рассматривать какую-то альтернативу dspam - может тот же spamassassin или rspamd. Одна из удобных особенностей для нашей среды была поддержка индивидуального пользовательского интерфейса в dspam, аутентификация по kerberos, поддержка клиент-серверной модели, не особая притязательность к ресурсам (хотя ночные задания обслуживания неплохо нагружали базу) - может кто-то что-то посоветует исходя из своего опыта?
Отказоустойчивость DSPAM
Добавлено: 2016-07-21 21:38:22
xM
Spamassassin всё это умеет. Единственный момент это то, что он на Perl. И хотя теперь он как-бы компилируется в бинарники, но скорость, конечно, ниже чем у написанных на C. Однако гибкость и всё такое у Spamassassin непревзойдённая.
Опять же Perl - бери и пиши свои модули сколько влезет.
Отказоустойчивость DSPAM
Добавлено: 2016-07-29 13:15:17
Andrey12
xM, не подскажите какой-то веб-интерфейс для SA?
Основные требования (в порядке важности):
1) индивидуальные пользовательские настройки
2) аутентификация доменных (AD) пользователей
3) русский интерфейс
4) поддержка карантина
Установил webuserprefs - не очень подходит, т.к. нет русского интерфейса, аутентификация выполняется через IMAP и т.п., а не по NTLM/Kerberos, нет карантина. Судя по скриншотам у php-sa-mysql функционал в принципе аналогичен.
Отказоустойчивость DSPAM
Добавлено: 2016-07-29 15:01:21
xM
Andrey12 писал(а): xM, не подскажите какой-то веб-интерфейс для SA?
Эээ... А он нужен вообще? Ни разу за годы работы такой потребности не возникало.
По пользовательским настройкам есть плагин для Roundcube
SAUserPrefs, который является у нас основным корпоративным клиентом. Однако, на практике им никто не пользуется, поскольку SA на автомате и с помощью механизма пользовательского контроля (плагин MarkAsJunk2 +
отложенное пакетное обучение) прекрасно справляется со своими обязанностями.
Отказоустойчивость DSPAM
Добавлено: 2016-08-02 18:20:26
Andrey12
Спасибо, возьму на заметку.
И еще момент по поводу недоступности SA. Установил в тестовой среде на отдельном сервере и вижу (конфигурация в принципе аналогична Вашей, но без Timeout'ов), что при его недоступности письмо просто передается далее без проверки - т.е. spamc (в transport_filter) возвращает то же письмо в command, но без заголовков SA. Т.е. defer по факту не происходит (насколько понимаю происходит только при таймауте.). Соответственно не нужно ничего мудрить с отказоустойчивостью. Для того чтобы мониторить такие ситуации сделал отдельный роутер, который передает письма на smarthost в случает отсутствия проверок SA (плюс доп. условия) - соответственно будет периодически мониторится лог на вхождение названия этого роутера.
Отказоустойчивость DSPAM
Добавлено: 2016-08-03 13:21:07
xM
Andrey12 писал(а): Т.е. defer по факту не происходит
Да, если что-то типа connection refused то не происходит. Но в транспортах, насколько я помню, есть механизм мониторинга ошибок через STDERR.