Защита от спама почтового сервера

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

Postfix и защита от спама

После установки и настройки Postfix, следует задуматься о защите его от разного рода “паразитов”, а точнее спаммеров.

Фильтр Postgrey

Материал из Википедии: Серые списки (англ. Greylisting) — способ автоматической блокировки спама, основанный на том, что «поведение» программного обеспечения, предназначенного для рассылки спама, отличается от поведения обычных серверов электронной почты. Если почтовый сервер получателя отказывается принять письмо и сообщает о «временной ошибке», сервер отправителя обязан позже повторить попытку. Спамерское программное обеспечение в таких случаях, обычно, не пытается этого делать.

Если вы используете Calculate Linux, то postgrey в нем уже установлен, остается только настроить:

vi /etc/postfix/main.cf

#Greylisting
smtpd_recipient_restrictions = permit_mynetworks, reject_unauth_destination, check_policy_service inet:127.0.0.1:10030

/etc/init.d/postgrey start
rc-update add postgrey default
/etc/init.d/postfix restart

И проверяем что пишется в логах:

tailf /var/log/messages

Recipient address rejected: Greylisted for 300 seconds; from= to=

Фильтр SPAMASSASSIN

Spamassassin - исследует содержимое письма, и назначает баллы за всевозможные признаки спама. Если количество баллов превышает допустимый предел (обычно - 5), то письмо признается как спам. Для его подключения отредактируем master.cf.

vi /etc/postfix/master.cf

В начале ищем строчку:

smtp      inet  n       -       n       -       -       smtpd

и дописываем в ее конец -o content_filter=spamassassin

smtp      inet  n       -       n       -       -       smtpd -o content_filter=spamassassin

Теперь в конце файла помещаем:

spamassassin
         unix  -       n       n       -       -       pipe
  user=spam argv=/usr/bin/spamc -e /usr/sbin/sendmail -oi -f ${sender} ${recipient}

Далее добавляем пользователя для работы антиспама

useradd -g nobody -d /var/calculate/server-data/mail/spam -s /bin/false spam

Создадим рабочий каталог для этого пользователя

mkdir /var/calculate/server-data/mail/spam

И права

chown spam:nobody /var/calculate/server-data/mail/spam

Этот каталог нам может понадобится в дальнейшим, для ручного составления черного и белого списков.

Запускаем и прописываем spamd

/etc/init.d/spamd start
rc-update add spamd default
/etc/init.d/postfix restart

Далее смотрим логи.

tailf /var/log/messages | grep spam

Nov 25 18:20:59 calculate spamd[17307]: spamd: connection from calculate.local [127.0.0.1] at port 55332
Nov 25 18:20:59 calculate spamd[17307]: spamd: setuid to spam succeeded
Nov 25 18:20:59 calculate spamd[17307]: spamd: processing message  for spam:1002
Nov 25 18:21:04 calculate spamd[17307]: spamd: clean message (1.2/5.0) for spam:1002 in 5.5 seconds, 1160 bytes.
Nov 25 18:21:04 calculate spamd[17307]: spamd: result: . 1 - AWL,LOCALPART_IN_SUBJECT   scantime=5.5,size=1160,user=spam,uid=1002,required_score=5.0,rhost=calculate.local,raddr=127.0.0.1,rport=55332,mid=,autolearn=no
Nov 25 18:21:04 calculate postfix/pipe[18124]: 0441852914: to=, relay=spamassassin, delay=5.5, delays=0.03/0.01/0/5.5, dsn=2.0.0, status=sent  (delivered via spamassassin service)
Nov 25 18:21:04 calculate spamd[17302]: prefork: child states: II
Nov 25 18:23:09 calculate spamd[17307]: spamd: connection from calculate.local [127.0.0.1] at port 55366
Nov 25 18:23:09 calculate spamd[17307]: spamd: setuid to spam succeeded
Nov 25 18:23:09 calculate spamd[17307]: spamd: processing message  for spam:1002
Nov 25 18:23:12 calculate spamd[17307]: spamd: identified spam (25.7/5.0) for spam:1002 in 2.3 seconds, 23878 bytes.
Nov 25 18:23:12 calculate spamd[17307]: spamd: result: Y 25 -   DC_GIF_UNO_LARGO,DC_IMAGE_SPAM_HTML,DC_IMAGE_SPAM_TEXT,DYN_RDNS_AND_INLINE_IMAGE,EXTRA_MPART_TYPE,FAKE_REPLY_C,FH_HELO_EQ_D_D_D_D,HELO_DYNAMIC_HCC,HELO_DYNAMIC_IPADDR,HTML_IMAGE_ONLY_08,HTML_MESSAGE,HTML_SHORT_LINK_IMG_1,MIME_HTML_MOSTLY,MPART_ALT_DIFF,RCVD_IN_PBL,RCVD_IN_SORBS_DUL,RCVD_IN_XBL,RDN S_DYNAMIC,TVD_FW_GRAPHIC_NAME_MID  scantime=2.3,size=23878,user=spam,uid=1002,required_score=5.0,rhost=calculate.local,raddr=127.0.0.1,rport=55366,mid=,autolearn=spam
Nov 25 18:23:12 calculate postfix/pipe[18163]: 1144C49CF7: to=, relay=spamassassin, delay=5.2, delays=2.9/0/0/2.3, dsn=2.0.0, status=sent    (delivered via spamassassin service)
Nov 25 18:23:12 calculate spamd[17302]: prefork: child states: II

Как видим, второе письмо - identified spam, и мало того - autolearn=spam! То есть, в базу “знаний” spamassassin - занесены признаки грязного спаммера. Я рискнул включить самообучение в /etc/spamassassin/local.cf

vi /etc/spamassassin/local.cf

bayes_auto_learn 1

Вы сами должны решить, нужно-ли вам самообучение и другие возможности spamassassin. Тут главное не переборщить :slight_smile:

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

Ручное обучение spamassassin

Помимо автообучения, эффективность задержания спама, можно значительно повысить с помощью “ручного” обучения фильтра. Это достигается путем “скармливания” фильтру правильной почты и спама с помощью програмы - sa-learn. Вот как это делается:

sa-learn --ham 
sa-learn --spam

На деле это не совсем удобно, но процес можно упростить, используя cron и почновый клиент, который работает с сервером через imap. Для этого в почтовом клиенете, в корне дерева IMAP - создайте две папки: HAM и SPAM. При обучении, вы будете в эти папки копировать, или переносить письма. Нужные письма в папку “HAM”, и спам в папку “SPAM”. Далее, на сервере, допустим в /usr/local/bin создадим скрипт под названием learn.

#!/bin/bash

 # путь к домашнему каталогу пользователя,·
 # который будет заниматься обучением spamassassin-а
ADMIN="/var/calculate/server-data/mail/sergey"

 # Путь кдомашнему каталогу учётной записи для spamassasin
SPAM="/var/calculate/server-data/mail/spam"

cd $SPAM/.spamassassin

if [ `ls $ADMIN/.INBOX.HAM/cur/ | grep -v "^\.$" | grep -v "^\.\.$" | wc -l` = "0" ];then
·       echo "Тут нету файлов для обучения spamassassin"
else
·       mv $ADMIN/.INBOX.HAM/cur/* $SPAM/.spamassassin/ham/
fi


if [ `ls $ADMIN/.INBOX.HAM/new/ | grep -v "^\.$" | grep -v "^\.\.$" | wc -l` = "0" ];then
·       echo "Тут нету файлов для обучения spamassassin"
else
·       mv $ADMIN/.INBOX.HAM/new/* $SPAM/.spamassassin/ham/
fi


if [ `ls $ADMIN/.INBOX.SPAM/cur/ | grep -v "^\.$" | grep -v "^\.\.$" | wc -l` = "0" ];then
·       echo "Тут нету файлов для обучения spamassassin"
else
·       mv $ADMIN/.INBOX.SPAM/cur/* $SPAM/.spamassassin/spam/
fi


if [ `ls $ADMIN/.INBOX.SPAM/new/ | grep -v "^\.$" | grep -v "^\.\.$" | wc -l` = "0" ];then
·       echo "Тут нету файлов для обучения spamassassin"
else
·       mv $ADMIN/.INBOX.SPAM/new/* $SPAM/.spamassassin/spam/
fi

PATHSPAM="$SPAM/.spamassassin"

if [ `ls $PATHSPAM/spam/  | grep -v "^\.$" | grep -v "^\.\.$" | wc -l` = "0" ];then
·       /bin/echo "SPAM: Тут нету файлов для обучения spamassassin"
else
sa-learn -u spam --spam --dbpath = $PATHSPAM/ $PATHSPAM/spam/*
rm $PATHSPAM/spam/*
fi

if [ `ls $PATHSPAM/ham/  | grep -v "^\.$" | grep -v "^\.\.$" | wc -l` = "0" ];then
·       /bin/echo "HAM: Тут нету файлов для обучения spamassassin"
else
sa-learn -u spam --ham --dbpath = $PATHSPAM/ $PATHSPAM/ham/*
rm $PATHSPAM/ham/*
fi

chown spam:nobody -R $SPAM/.spamassassin/

Дайте ему права:

chmod 555 /usr/local/bin/lern
chown spam:spam /usr/local/bin/lern

И попробуйте один раз проделать вышеизложенные действия с письмами. В домашнем каталоге для spamassassin /var/calculate/server-data/mail/spam должны появится файлы

=_seen
=_toks

Сделайте символьные линки:

ln -sf bayes_seen =_seen
ln -sf bayes_toks =_toks

Еще создайте 2 каталога

mkdir /var/calculate/server-data/mail/spam/.spamassassin/{ham,spam}

И снова запустите скрипт для установки доступа и апдейта баз спама. Следите за датой файлов bayes_* - она должна меняться после процедуры обучения и запуска скрипта.

И последнее, пропишите этот скрипт в cron

crontab -e
*/10 * * * * /usr/local/bin/learn 2>&1 > /dev/null

Каждые 10 мин будет запускаться скрипт и проверять что вы ему предоставили для обработки в почтовом клиенте.

Настройка “строгих” директив в Postfix

Подробнее о антиспамных директивах в main.cf написано тут: http://www.sergeysl.ru/postfix-mail-system/

vi /etc/postfix/main.cf

body_checks = regexp:/etc/postfix/body_checks
header_checks = regexp:/etc/postfix/header_checks

Не общаться с почтовыми системами, которые не знают имени своего хоста.

smtpd_helo_restrictions =  permit_mynetworks, reject_unknown_hostname, reject_invalid_hostname, reject_non_fqdn_hostname,  reject_unknown_sender_domain, reject_unknown_recipient_domain

Не принимать почту от доменов, которые не существуют.

smtpd_sender_restrictions = reject_unknown_sender_domain

Блокировать клиентов, которые начинают общаться рано.

#smtpd_data_restrictions = reject_unauth_pipelining

Отклонять команду ETRN

smtpd_etrn_restrictions = reject

Запретить исходящую почту с наших доменов, но с несуществующих у нас адресов

smtpd_reject_unlisted_sender = yes

Запретить письма для неизвестных адресов получателей

smtpd_reject_unlisted_recipient = yes

Отключает SMTP команду VRFY. В результате чего, невозможно определить существование определенного ящика.·
Данная техника (применение команды VRFY) используется спамерами для сбора имен почтовых ящиков.

disable_vrfy_command = yes

Требует команды helo от подсоединившихся клиентов

smtpd_helo_required = yes

требует окружать полученные в MAIL FROM и RCPT TO адреса угловыми скобками , а также, чтобы они не содержали лишних фраз

strict_rfc821_envelopes = yes

Всегда отправлять EHLO вначале SMTP сессии

smtp_always_send_ehlo = yes

Ожидание до RCPT TO перед выяснением

smtpd_client_restrictions, smtpd_helo_restrictions и smtpd_sender_restrictions

# или до ETRN перед выяснением smtpd_client_restrictions, smtpd_helo_restrictions.·
# Такое поведение еще обеспечивает лучшую читаемость логов.

smtpd_delay_reject = yes

# Максимальное количество ошибок, которое может сделать удаленный SMTP клиент. При превышение данного числа Postfix отсоединится.

#smtpd_hard_error_limit = 1

# Интервал времени в течение которого SMTP сервер Postfix должен послать ответ, а удаленный SMTP клиент получить запрос

smtpd_timeout = 30s

# Интервал времени, в течение которого SMTP клиент должен послать SMTP команду HELO или EHLO и получить ответ сервера.

smtp_helo_timeout = 15s

# Интервал времени, в течение которого SMTP клиент должен послать SMTP команду RCPT TO и получить ответ сервера.

smtp_rcpt_timeout = 15s

# ограничение на количество одновременных получателей письма, по умолчанию 1000 :slight_smile:

smtpd_recipient_limit = 40

# Время хранения в очереди боунсов

bounce_queue_lifetime = 1d

# Время хранения в очереди обычных писем, может принимать значения: s (seconds), m (minutes), h (hours), d (days), w (weeks).

maximal_queue_lifetime = 3d

# Минимальный интервал повторной отправки писем (если получатели использую грейлистинг небольшое значение этого интервала·
# позволяет немного уменьшить очередь, по умолчанию здесь слишком большое значение в 4000s)

minimal_backoff_time = 180s

# Максимальный интервал повторной отправки писем. Письма которые уже давно лежат в очереди будут повторно·
# отправляться раз в 6 часов. По умолчанию здесь наоборот маленькое значение.

maximal_backoff_time = 6h

думаю что новичкам и ленивым статья поможет, только вот по поводу postgrey:

  • можно было-бы написать хоть немного поболее
  • учитывая “серверность” решения - логичнее было-бы прикрутить его к PostgreSQL …

Yuri Stepanov писал(а):

думаю что новичкам и ленивым статья поможет, только вот по поводу postgrey:
postgrey
* можно было-бы написать хоть немного поболее
* учитывая “серверность” решения - логичнее было-бы прикрутить его к PostgreSQL …

Юрий, я не совсем понял вопроса. Ты спросил про postgrey, или PostgreSQL? postgrey - это не база данных! Это что-то типа фильтра для спама, который всего навсего не принимает первый коннект почтовика.
А баз данных много, и прикручивать можно любую. Все зависит от количества юзеров. Если их не много, то база имхо не нужна. С ней только геморов прибавится. Другое дело когда юзверей под тысячу.
Или что ты имел в виду?

Именно то, что написал - сконфигурировать postgrey для хранения своих данных в БД. Т.к. в качестве “дефолтной” БД у нас принята PostgreSQL - то соответственно для нее.
По поводу “Это что-то типа фильтра для спама, который всего навсего не принимает первый коннект почтовика” - на самом деле postgrey делает несколько “поболее” :wink: И не все зависит от количества юзеров - в большей степени от “популярности” домена и количества почты. Даже при двух десятках клиентов я бы приветствовал хранение данных postgrey в БД, гемора только убавляется - postgrey еще ни разу не зависал при работе со своими “родными” базами? :wink:

Именно то, что написал - сконфигурировать postgrey для хранения своих данных в БД. Т.к. в качестве “дефолтной” БД у нас принята PostgreSQL - то соответственно для нее.

Так может напишешь мануал?

По поводу “Это что-то типа фильтра для спама, который всего навсего не принимает первый коннект почтовика” - на самом деле postgrey делает несколько “поболее” :wink:

Надо-же! А мужики-то не знают! :slight_smile:

Так может напишешь мануал?
Надо-же! А мужики-то не знают!

Вместо копипаста лучше просто брошу ссылочку на дочерний ресурс - http://ru.gentoo-wiki.com/wiki/Настройка*почтового*сервера_(Postfix,_Dovecot,_DSpam,_SQLGrey,_DomainKeys,_SPF)#.D0.9D.D0.B0.D1.81.D1.82.D1.80.D0.BE.D0.B9.D0.BA.D0.B0_SQLGrey

Yuri Stepanov писал(а):

Так может напишешь мануал?
Надо-же! А мужики-то не знают!

Вместо копипаста лучше просто брошу ссылочку на дочерний ресурс - http://ru.gentoo-wiki.com/wiki/Настройка*почтового*сервера_(Postfix,_Dovecot,_DSpam,_SQLGrey,_DomainKeys,_SPF)#.D0.9D.D0.B0.D1.81.D1.82.D1.80.D0.BE.D0.B9.D0.BA.D0.B0_SQLGrey

Спасибо, действительно хорошая статья! Но как я понял, не всё доделано? Там у тебя чтото про секурность.
Ну выложил-бы ты её сюда! Чего лениться-то?