Борьба со спамом - это головная боль всех ответственных администраторов почты. В этой статье собраны методы фильтрации спама на основе анализа только SMTP заголовков письма. Примеры настройки почтового сервера приведены для Postfix.

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

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

Небольшая замечание: статья написана с прицелом на настройку почтового сервера Postfix, но в целом носит скорей теоретический характер. Описанные опции Postfix нужно указывать в соответствующих *_restriction параметрах конфигурационного файла, за подробностями обращайтесь к любому руководству по настройке Postfix.

Немного об SMTP протоколе

Электронная почта имеет много аналогий с почтой обычной. Самое для нас главное сейчас то, что вся информация на электронном «конверте» представляет из себя всего лишь два адреса: получателя и отправителя, а также штампик почтальона, конверт доставившего.

Немного отвлечёмся: представьте, что к вам придёт лицо крайне отталкивающей наружности и вручит плотно запечатанную посылку с обратным адресом «Трям из Тилимилитрямдии». Рискнёте принять и открыть? Вряд ли. Так вот, электронную почту можно тоже легко проверять и отсеивать исходя только из адресной информации, причём простор для возможных действий тут гораздо шире.

Как вам должно быть известно, почта в интеренете передаётся между почтовыми серверами по протоколу SMTP. Любое общение по этому протоколу начинается с трёх обязательных заголовков: HELO, MAIL FROM и RCPT TO. То есть перед тем, как начать передавать какие-либо данные, сервер сначала представляется (HELO), потом сообщает обратный адрес отправителя (MAIL FROM) и затем - адрес получателя (RCPT TO). Эти три заголовка и есть подпись на электронном конверте, и практически весь спам можно отсеять только исходя из их анализа. Большинство попыток передать что-то моему серверу не доходят дальше MAIL FROM, то есть письма отсеиваются ещё до фактического принятия, что значительно снижает нагрузку. То есть вместо того, чтобы открыть посылку от Тряма и обнаружить там споры сибирской язвы, я сразу посылаю почтальона куда подальше.

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

Немного о DNS

Когда-то на заре Интернета почта доставлялась непосредственно на узлы, указанные в почтовом адресе. То есть для доставки письма для user@domain.com почтовый сервер искал IP адрес domain.com и пытался послать посылочку по найденному IP. Потом появились MX записи, которые разом решили большинство проблем подобной организации почтового взаимодействия. Однако некоторые программы всё ещё могут работать с A записями при доставке почты. Но у вас, конечно, есть хотя бы одна MX запись для вашего домена, не так ли?

MX записи содержат адреса серверов, на которые должны доставляться письма для указанного домена. Однако в целях борьбы со спамом появилась технология, позволяющая указывать в DNS также адреса серверов, с которых могут приходить письма от указанного домена. Имя ей - Sender Policy Framework.

Подробно вдаваться во все тонкости технологии я не буду, скажу лишь, что TXT запись

v=spf1 +mx ~all

для вашего домена скажет всем клиентам, поддерживающим проверку SPF, что письма из вашего домена вообще говоря должны приходить с серверов, указанных в MX записях. Можно сделать правило жёстче, написав вместо ~all -all. За подробностями обращайтесь в Google и на официальный сайт SPF.

Учтите, что письма могут идти через ретрансляторы. Многие почтовые домены в интернете являются всего лишь ретрансляторами. Поэтому жёсткий запрет в SPF записях, а так же отсеивание спама только исходя из SPF информации, являются крайне нежелательными. Однако всё же всегда прописывайте SPF запись для домена, а так же включайте проверку SPF на своих почтовых серверах.

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

Есть ещё пару крайне важных замечаний по поводу DNS. Скорее всего вы знаете, что основные записи DNS, так называемые A записи, преобразуют имя в IP адрес. Кроме них есть ещё CNAME записи, которые назначают псевдоним уже существующему имени. Именно эти два типа записей составляют основу всей системы доменных имён.

Но мало кто из пользователей знает, что есть так же обратные записи, которые преобразуют IP в доменное имя. Они носят название PTR. Так вот, есть два неписаных (строго говоря) правила, которым всё же все следуют:

  1. Для каждой A записи должна существовать зеркальная PTR запись, то есть по имени хоста через DNS получаем IP, а по IP - обратно то же имя хоста.
  2. В качестве адреса в MX записи всегда должно стоять имя (не IP!) хоста, для которого существует A запись. То есть нельзя, чтобы в MX записи стоял IP или псевдоним (CNAME).

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

Присматриваемся к клиенту

Итак, SMTP сессия начинается с попытки подключения от клиента. Соответственно вы получаете его IP и можете сделать кое-какие выводы только на его основании. Например, вы можете включить проверку PTR записи для клиента, для это используйте опцию

reject_unknown_client_hostname

Она требует, чтобы IP, с которого совершается соединение, резолвился в имя через PTR, а это имя резолвилось в свою очередь обратно в искомый IP.

Есть и менее жёсткое ограничение, задаваемое опцией

reject_unknown_reverse_client_hostname

В этом случае сервер будет проверять только наличие PTR записи, но не будет требовать существования соответствующей записи A.

Есть ещё один трюк. Можно заставить свой сервер отвечать клиенту не сразу, а с небольшой задержкой. Это поможет отсечь много спама, поскольку спамерам ждать некогда. В то же время нормальный SMTP сервер никогда не порвёт соединение, не подождав хотя бы нескольких секунд. Ждать можно на любом этапе общения, но эффективней это делать сразу после получения запроса на соединение от клиента (то есть просто немного затянуть с ответом), поскольку когда вы уже начнёте общение, то задержки вряд ли заставят клиента отключиться.

Для включения таймаута служит опция

sleep seconds

Не указывайте время ожидания больше 25 секунд. По умолчанию тот же Postfix после 30-ой секунды ожидания считает, что сервер недоступен, так что разумным ограничением на используемое время задержки можно считать 20 секунд или около того.

Проверяем приветствие

Итак, кто-то захотел передать вашему серверу письмо. Передача начинается с приветствия - заголовка HELO. В HELO должно быть указано полное доменное имя (FQDN) отправителя, соответственно если это не так - можете смело сразу же отказывать в принятии. В Postfix для этого служат две опции:

reject_invalid_helo_hostname
reject_non_fqdn_helo_hostname

Первая запрещает приём писем от хостов, передающих приветствие с некорректным синтаксисом, вторая - от хостов, передающих не FQDN в HELO запросе.

Однако не FQDN передают только самые глупые спамеры (и продукты MS, но им, как известно, законы не писаны), в конце концов представиться gmail.com не составляет труда. Поэтому надо ещё немного присмотреться к HELO. Для этого служат опция

reject_unknown_helo_hostname

Которая запрещает приём писем от серверов, представляющихся адресом, для которого не существует A или MX записи.

Согласно RFC 5321 клиенты SMTP обязаны начинать сессию с команды EHLO (HELO) и представляться своим полным доменным именем (FQDN) или полным IP адресом в случае отсутствия доменного имени. Поскольку почтовые серверы в интернете не могут не иметь доменного имени - то все предложенные в этом разделе проверки включать можно с чистейшей совестью.

Отправитель - а стоит ли ему доверять?

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

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

reject_non_fqdn_sender
reject_unknown_sender_domain

Первая - проверка адреса на написание, вторая - проверка существования домена.

Уже неплохо, но можно сделать кое-что ещё. Можно запросить сервер, обслуживающий указанный адрес отправителя, на предмет существования на нём пользователя с этим адресом. Действительно, вроде бы неплохая идея удостовериться в том, что обратный адрес действительно существует, иначе нам вполне может придти письмо от эфемерного фантома, о котором никто и не слыхивал.

Технически это реализуется очень просто: наш сервер открывает встречную SMTP сессию, пытаясь послать письмо по адресу отправителя. Если удаётся успешно пройти этап посылки RCPT TO с этим адресом, т.е. если принимающий сервер вдруг не заявляет, что указанного ящика на нём нет, то считается, что присланный нам обратный адрес существует. Данные (то есть письмо) при проверке естественно никакие не передаются, сессия прерывается после RCPT TO.

За такую проверку обратного адреса отвечает опция

reject_unverified_sender

Из сказанного выше следует, что для любого адреса, с которого вы рассылаете почту из своего домена, должен существовать ящик на вашем сервере. Иначе ваши письма не пройдут проверку обратного адреса на стороне получателя и соответственно не будут доставлены по назначению. Это актуально для всяких рассылок и прочей вроде как односторонней коммуникации, не требующей ответа. Всегда создавайте ящики для всех адресов, с которых вы рассылаете почту. Если вы не хотите получать ответы на какой-то адрес, то просто посылайте письма на него в /dev/null, но принимать эти письма вы обязаны.

У обратной проверки адреса отправителя есть пару тонкостей: во-первых настроенный на обратную проверку адреса сервер очень легко можно использовать как посредника при DoS атаках. И правда: достаточно послать на ваш сервер много писем с несуществующими отправителями из какого-нибудь одного конкретного домена, и ваш сервер запросит у обслуживающего этот домен сервера информацию о существовании всех перечисленных отправителей. Правда злоумышленник с таким же успехом может атаковать нужный ему сервер напрямую, так что реально вы вряд ли сможете сильно помочь кому-то в организации DoS атаки. Ну а во-вторых документы RFC вообще говоря обязывают принимать почту с пустым MAIL FROM (см. RFC 2505).

А получатель-то вообще существует?

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

reject_non_fqdn_recipient

Кроме того нам бы не хотелось принимать почту на адреса, для которых у нас нет почтовых ящиков. Чтобы настроить такое поведение надо сначала создать список обслуживаемых ящиков, дальше рассказать о нём Postfix через один из *_recipient_maps параметров конфигурационного файла, ну а дальше либо воспользоваться параметром конфигурационного файла

smtpd_reject_unlisted_recipient = yes

Либо запрещающей опцией, имеющей тот же эффект:

reject_unlisted_recipient

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

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

reject_unauth_destination

Она запрещает отсылку писем всем незарегистрированным пользователям (да, вам придётся настроить SMTP авторизацию или добавить нечто вроде permit_mynetworks).

Всегда используйте эту опцию! Иначе быстро попадёте во всякие DNSBL.

В качестве промежуточного итога

Вот так только на основе анализа трёх заголовков конверта можно отсеять огромное количество спама. Однако спамеры хитрые, поэтому этого всё же недостаточно.

Грейлистинг

Иногда почтовые серверы бывают перегружены и не могут принять письмо. Как вы думаете, что они отвечают на входящие запросы в этом случае? Как ни странно так и отвечают - сервер временно недоступен, попробуйте позже. Ни один нормальный отправитель никогда в этом случае не посчитает, что письмо доставить нельзя со всеми вытекающими последствиями. Напротив, отправитель предпримет попытки доставить письмо позже, поставив его в свою очередь на отправку. Этот факт можно (и без сомнения нужно!) очень эффективно использовать: при каждой первой попытке соединения с незнакомого хоста наш сервер будет отправлять сообщение о временной ошибке, а пропускать письмо только со второго раза. Это отсеит сразу чуть ли не весь оставшийся спам, поскольку спамсерверы практически никогда не предпринимают больше одной попытки доставки письма (иначе они бы просто «упали» от переполнения очереди). Эта технология называется Greylisting, и использовать её в современных реалиях просто необходимо.

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

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

Блоклисты, или как делать не надо

Некоторые администраторы почты при фильтрации спама полагаются на так называемые DNSBL (RBL) - чёрные списки узлов, замеченных в рассылке спама. Так вот, никогда не добавляйте никаких проверок DNSBL на ваши почтовые сервера. Тому есть две причины: первая, и самая основная, кроется во второй части первого предложения этого раздела. В эти списки узлы заносятся совершенно беспорядочно и нет никаких гарантий, что туда не попадёт нормальный хост (на котором, может быть, в какой-то момент поселился вирус, рассылающий спам, но теперь вирус уже вылечили, или проще и гораздо реальней - один внешний IP для большой сети, в которой завёлся спамер). Вторая причина более банальна: предложенный выше механизм фильтрации гораздо эффективней любых DNSBL и при этом не полагается на непроверенные данные от третьих лиц. DNSBL, не смотря на любовь к ним многих администраторов - однозначно порочная технология, и она ни в коем случае не должна применяться в чистом виде на серверах. Для примера.

С ног на голову, или посмотрим с другой стороны баррикад

Фильтровать спам научились, теперь же постараемся свести воедино всю информацию на тему того, что же надо делать, что бы не попасть в спам.

Для администраторов почтовых серверов:

  1. Всегда делайте MX записи ссылающимися на записи A.
  2. Запись A для почтового сервера всегда должна иметь зеркальную PTR запись.
  3. Хост из HELO заголовка должен иметь A или MX запись.
  4. Всегда создавайте SPF записи (да-да, это-то как раз не обязательно, но просто правило хорошего тона).
  5. Для всех писем, рассылаемых из обслуживаемого домена, ящик для обратного адреса должен существовать и принимать почту.

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

  1. Всегда посылайте почту только с существующим обратным адресом.
  2. Никогда не посылайте почту с неподконтрольного вам домена, не проверив правила SPF для него. Например gmail.com в текущий момент позволяет посылать письма от его имени любому серверу, а вот yandex.ru и mail.ru сообщают через SPF о том, что посылка от их имени со сторонних серверов должна вызывать на себя пристальное внимание, что истолковывается умными спамфильтрами как увеличение уровня оценки спама для данного письма.
  3. Никогда не посылайте почту через неправильно настроенные SMTP серверы. Проверить сервер на вшивость по списку выше - дело 5 минут, вам поможет утилита dig или nslookup.

Резюме

Конечно, предложенные настройки фильтруют не весь спам. Поэтому вполне возможно вам потребуется дополнительно использовать ещё и контекстный фильтр, который будет анализировать содержание писем, например, Spamassassin.

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

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

Хотите что-то добавить?

Вы находитесь в Wiki разделе. Поэтому можете смело исправлять статью и добавлять в неё новые данные (например, описание поддержки предложенных механизмов другими почтовыми серверами). Однако в данном конкретном случае старайтесь сохранять целостность повествования и не отклоняйтесь от основной темы - перечисления возможностей фильтрации спама на основании только SMTP заголовков.

Небольшие комментарии по поводу Postfix

Во-первых, как уже было сказано, все приведённые опции надо указывать в одном из четырёх *_restrictions параметров конфигурационного файла Postfix, относящихся к заголовкам SMTP сессии. Первый из них, smtpd_client_restrictions отвечает за проверки на основе IP адреса клиента, оставшиеся три - smtpd_helo_restrictions, smtpd_sender_restrictions и smtpd_recipient_restrictions - за соответствующие SMTP заголовки.

При этом обратите внимание на то, что все четыре параметра применяются последовательно, и при этом если письмо отклоняется хотя бы в одном - то оно не принимается и отправителю посылается ошибка. Однако permit правила отменяют дальнейшие проверки только по данному конкретному параметру, и Postfix переходит к следующему. Поэтому если письмо успешно прошло проверку по smtpd_client_restrictions, то оно вполне может отсеяться по smtpd_helo_restrictions.

Кроме того, современные версии Postfix по умолчанию отклоняют письмо не раньше RCPT TO команды. Это сделано для того, что бы в логах всегда можно было посмотреть полную информацию о письме - от кого и кому оно должно было придти. Не стоит менять такое поведение Postfix.

Ну и наконец есть возможность протестировать любую reject_* опцию без реального отклонения писем. Для этого необходимо перед ней в соответствующем параметре конфигурационного файла Postfix указать опцию warn_if_reject. При этом в случае срабатывания запрета в логфайл будет добавлена запись с пометкой reject_warning, однако письмо не будет отклонено.

Подробней про возможные запрещающие опции и параметры конфигурационного файла Postfix можно почитать в официальной документации:

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

Ссылки