2008-06-05

Публикации Как тестировать почтовую службу Несколько слов о социальных сервисах

Как организовать вспомогательный почтовый узел

Андрей Орлов  2008-06-05 11:00

Как догадываются внимательные читатели, я не только тесты рассылаю, но и сервер почтовй поддерживаю :), спам фильтрую и типа того. В этой статье описан наш опыт организации вспомогательных почтовых узлов (MX-серверов), в котором использовалась распределенная база адресов, реализованная посредством SMTP-протокола. Такое решение представляется более разумным, чем настройка еще одной службы (например, LDAP): чем меньше софта и проще решение - тем оно надежнее. Впрочем, читайте подробности в статье и пробуйте сами.

Как организовать вспомогательный почтовый узел

Как организовать вспомогательный почтовый узел

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

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

Кроме того, почтовые узлы позволяют разгрузить почтовый сервер от (ресурсоемкой) первичной обработки почты, связанной с фильтрацией обращений от недобросовестных отправителей.

Введение в проблему

Организация вспомогательного почтового узла - это легкое и простое дело. Почти. Вносится пара записей в DNS (A и MX), поднимается сервер, на нем настраивается передача всей почты домена на основной почтовый сервер и все. Почти.

Вот с этого "почти" и начинаются проблемы. Одна из них - в современном мире почтовый узел не может принять почту, если не уверен, что может доставить ее адресату. Следовательно, почтовому узлу должен быть доступен список всех адресов, существующих на почтовом сервере. В противном случае почтовый узел начнет принимать весь приходящий на него спам, направленный на неизвестные адреса (и создаст большой траффик), а письма "пользователь недоступен" в ответ на этот спам начнет рассылать почтовый сервер, что неминуемо начнет беспокоить пользователей Интернет и сервер попадет в черный список. Если же почтовый узел сразу скажет "нет", то в черный сервер, пытавшийся отправить спам пользователям домена.

Решение при помощи relay policing

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

  1. База уже существует на почтовом сервере;

2. SMTP-протокол может быть использован как протокол запросов к базе адресов через SMTP-соединение.

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

Механизмы принятия решения могут быть самыми разным (известны демоны, выполняющие greylisting, SPF и т.п.). В случае relay policing, демон, запущенный на вспомогательном почтовой узле, проверяет существование адреса на основном почтовом сервере.

Упрощенный алгоритм работы

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

Упрощенный алгоритм работы подразумевает, что при невозможности обратится к основному серверу, почтовый узел отказывает в приеме письма со статусом со статусом "Временно недоступен" или аналогичным (4xx).

Кеширующий relay policing

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

Кеш
Кеш запросов к основному почтовому серверу, позволяющий по адресу определить время внесения записи в кеш и логическое значение, истинное в том случае, если адрес существует на основном сервере.
Таймаут
Максимальный возраст записи в кеше.
  1. Для адреса получателя, полученого демоном, найти значение в кеше;
  2. Если логическое значение из кеша не старее, чем таймаут, то при истинном значении вернуть серверу команду "принять почту", иначе - "отказать в приеме", перейти на 4;
  3. Если в кеше не существует значения или оно устарело, то адрес валидируется на основном почтовом сервере. Возможный результат валидации: "Адрес существует", "Адрес не существует", "Сервер недоступен";
3.1. При результате "Адрес существует", отдать серверу команду
"принять почту", внести результат в кеш;
3.2. При результате "Адрес не существует", отдать серверу команду
"отказать в приеме", внести результат в кеш;
3.3. При результате "Сервер недоступен", отдать серверу команду
"отложить прием почты".
  1. Конец алгоритма.

Алгоритм требует, чтобы основной сервер давал ответ о существовании адреса получателся независимо от адреса отправителя. Кроме того, основной сервер никогда не должен отказывать в приеме почты по каким-либо "особым" причинам (например, RBL-листы и т.п.), что достаточно легко обеспечить. Если эти условия выполнить невозможно - алгоритм может быть доработан.

Результаты практической эксплуатации

Опытная эксплуатация relay policing daemon проводилась на postfix-сервере, служащего сервером входящей почты для сервера Microsoft Exchange, выполняющего для него фильтрацию спама (RBL, greylisting, spamassasin) и почты, зараженной вирусами (clamav). Такое решение позволило резко снизить ресурсоемкость Microsoft Exchange (в отсутствии postfix-сервера на сервере MS Exchange исчерпывались ресурсы практически моментально и его работа прекращалась). Изначально, использование такого алгоритма было обусловлено сложностью обеспечения доступа сервера postfix к базе адресов MS Exchange.

Количество адресов в MS Exchange составляло около 200. В процессе эксплуатации использовался таймаут в 24 часа на удачные и неудачные записи, что приводило к небольшой доле (один раз в сутки) фиктивных обращений к серверу Exchange.

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

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

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

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

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

Реализация relay policing демона

Приведем упрощенный фрагмент кода relay policing демона, использованного в нашей опытной эксплуатации:

from smtplib import SMTP, quoteaddr
from bsddb import btopen
from marshal import dumps,loads

def check(cfg,sender,recipient) :
    """ Вернуть результат проверки адреса на основном сервере и напечатать
    решение демона для почтового узла """
    smtp = SMTP()

    try :
        code, res = smtp.connect(cfg['relay'],cfg['port'])
    except Excepton,msg :
        # Сервер недоступен
        print "action=defer_if_permit Service temporarily unavailable"
        return 1

    if code == 220 :
        code, res = smtp.helo()
        if code == 250 :
            code, res = smtp.docmd('mail from:',quoteaddr(sender or ""))
            if code == 250 :
                code, res = smtp.docmd('rcpt to:',quoteaddr(recipient or ""))
                if code == 250 :
                    # Адрес существует
                    print "action=dunno"
                    return 0

    # Адрес не существует
    print "action=reject"
    return 2


def cache(db,cfg,sender,recipient) :
    """ Кешировать результат проверки адреса """

    try :
        tb,haveaddr = loads(db[key])
    except KeyError :
        # Адреса нет в кеше, выполняем проверку
        res = self.check(cfg,sender,recipient)

        # Вносим адрес в кеш, если удалось обратится к серверу
        if res in [0,2] :
            db[key] = dumps((t,0==res))
    else :
        #  Адрес есть в кеше
        if t - tb > cfg["delay"] :
            # Адрес в кеше устарел, выполняем проверку
            res = self.check(cfg,sender,recipient)

            # Обновляем данные в кеше, если удалось обратится к серверу
            if res in [0,2] :
                db[key] = dumps((t,0==res))
        elif haveaddr :
            # Адрес существует
            print "action=dunno"
        else :
            # Адрес не существует
            print "action=reject"

Кэш в этом примере хранился в bsddb.

Заключение

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

Хотя возможны другие подходы для решения этой задачи (LDAP, PostgreSQL+Notify, и т.п.), подход на основе relay policing внушает большую уверенность в своей надежности, так как практичесии не вносит новых функциональных точек в архитектуру почтовой службы.

DreamBot Zope3 Учат тут Нейросети Репозиторий Слив! Статистика Редакторам Мобильный блог
Официальный сайт Zope3 Московская группа изучения реактивного движения The Dream Bot Site nooxml Сайт посуточной аренды квартир в москве