SPF и DKIM – это механизмы верификации почтового сервера, позволяющие проверить его подлинность. Многие почтовые сервера используют их при получении почты, чтобы быть уверенным в том, что получаемая почта не является спамом. Если вы организуете рассылку со своего почтового сервера, например, периодическую рассылку, либо рассылку писем от вашего интернет-магазина, вам, скорее всего, придется настраивать оба механизма, поскольку это позволит быть уверенным в том, что ваши письма доставляются и автоматически не определяются как спам.

Настройка SPF (Sender Policy Framework).

Настройка SPF является достаточно простой. Для этого достаточно создать записи DNS, определяющие, с каких серверов разрешена отправка почты для данного домена. Использоваться могут два типа записи – TXT и SPF.

В данном примере указывается,  что отправка почты данного домена разрешена только с хоста с адресом <IP-адрес-почтового-сервера>, для которого есть записи типа A и MX, со всех остальных отправка запрещена.

После добавления записей не забудьте изменить serial для зоны DNS и перезагрузить информацию о доменной зоне. Если вы всё сделали правильно, то при отправке письма на другой домен, например, на gmail.com, в заголовках письма вы увидите следующий заголовок:

Настройка DKIM (DomainKeys Identified Mail).

Настройка DKIM несколько сложнее, чем настройка SPF. Для работы этого механизма необходимо следующее:

– Почтовый сервер должен уметь подписывать письма
– Должны быть созданы приватный и публичный ключи
– Должны присутствовать записи в DNS, указывающие на наличие поддержки DKIM

Генерация ключей.

Ключи можно сгенерировать при помощи OpenSSL. Генерация приватного ключа:

После генерации приватного ключа необходимо изменить права доступа к нему:

Генерация публичного ключа:

Ключи готовы. Их можно разместить в директории, где хранятся другие ключи. Для Debian'а это директория /etc/ssl/private. Сгенерировать их можно также при помощи программы opendkim-genkey, входящую в пакет opendkim-tools. Теперь надо добавить записи в DNS. Записей будет две.

То, что идет после «p=» – это ключ, содержащийся в файле dkimpublic.key, он записывается в одну строчку. А запись «_adsp._domainkey.domain.ru» определяет, должны ли подписываться письма. Возможные варианты:
«dkim=all» – все письма должны подписываться
«dkim=discardable» – неподписанные письма не должны приниматься
«dkim=unknown» – то же самое, что и отсутствие такой записи.
После создания записей изменяем serial и перезагружаем настройки bind'а, если у вас установлен он. И теперь осталось последнее – настроить почтовый сервер. В качестве почтового сервера возьмем Postfix.

Настройка поддержки DKIM почтовым сервером Postfix.

Последняя и, пожалуй, самая важная часть – включение подписи писем почтовым сервером. Самое первое, что нужно сделать на этом этапе, – это установить opendkim:

Теперь необходимо настроить этот сервис. Первым делом поменяем файл /etc/default/opendkim. Впишем туда следующую строчку:

Теперь наш сервер будет запускаться на порту 10024 на loopback-интерфейсе. Следующий файл, который необходимо изменить, – это /etc/opendkim.conf.

Раскомментируем строчку со словом Domain, вписываем название нашего домена:

Теперь указываем файл с приватным ключом:

После этого указываем селектор, который мы использовали для сгенерированного ранее публичного ключа, указывая его в записи DNS. В нашем случае это «mail»:

Дописываем строчку:

Теперь можно рестартовать opendkim:

И последний шаг – настройка непосредственно Postfix'а. Изменяем файл /etc/postfix/main.cf. Добавим туда следующие строчки:

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

Если вы видите строчки «spf=pass» и «dkim=pass», значит вы все сделали правильно и ваш почтовый сервер теперь будет значительно лучше восприниматься другими почтовыми серверами, с чем я вас и поздравляю

Лог-файлы размещаются в каталоге /var/log/exim/:

  • текстовые файлы:
    exim_mainlog — текущий лог-файл работы почтового сервера
    exim_rejectlog — текущий лог-файл ошибок доставки корреспонденции
  • архивные файлы:
    exim_mainlog.0.gz —exim_mainlog.7.gz — архивы предыдущих лог-файлов работы почтового сервера
    exim_rejectlog.0.gz — exim_rejectlog.7.gz — архивы предыдущих лог-файловошибок доставки корреспонденции

Формат логов подробно описан в документации на exim. Основной сайт —www.exim.org.

Пример фрагмента лог-файла с подробной расшифровкой:
2004–04–13 07:38:59 1BDElF-0006fT-Jz@radiomayak.ru H=(interost.ru) [82.148.19.253] P=esmtp S=41294
2004–04–13 07:38:59 1BDElF-0006fT-Jz => alexey R=localuser T=local_delivery
2004–04–13 07:38:59 1BDElF-0006fT-Jz Completed

Первая строка — запись о принятии сообщения, на это указывают символы ’<=’.

Во всех записях первыми идут дата и время. Практически во всех записях далее идет внутренний идентификатор сообщения, здесь это 1BDElF-0006fT-Jz. Он одинаков для всех записей, относящихся к обработке одного и того же сообщения. Далее идет знак операции:
<= — прием
=> — доставка
— > — доставка за один прием сообщения на несколько адресов
== — сообщение отложено для последующей обработки из-за нефатальной ошибки
** — прекращение обработки из-за фатальной ошибки
Completed — обработка сообщения завершена.

В строках с знаком ’<=’:
сразу после знака идет адрес отправителя (аргумент SMTP команды MAIL FROM)
H=(…) — аргумент SMTP команды HELO или EHLO
[..] — IP адрес с которого принято сообщение
P=…. — протокол. Варианты:

  • smtp — SMTP, была дана команда HELO
  • esmtp — SMTP, была дана команда EHLO
  • asmtp — SMTP c авторизацией
  • local — сообщение передано локально — например вызовом команды sendmail из скрипта

S=… — размер сообщение в байтах
U=… — пользователь, от имени которого запускалась команда sendmail
R=… — идентификатор сообщения, в ответ на которое было порождено данное сообщение (обычно для сообщений об ошибке доставки)
id=… — собственный идентификатор сообщения (находится в заголовке Message-ID)

Таким образом, первая строка говорит о том, что 13 апреля в 07:38:59 с сервера 82.148.19.253, представившегося как interost.ru было принято сообщение размером 41294 байт с обратным адресом inform@radiomayak.ru.

В строках с знаком ’=>’ или ’->’:
сразу после знака идет адрес получателя. В случае локальной доставки перед ним идет имя почтового ящика.
R=… — название использовавшегося роутера. В наших типовых настройках это:

  • localuser — в локальный почтовый ящик
  • shadow_autorep — автоответчик с доставкой сообщения
  • regular_autorep — автоответчик без доставки
  • lookuphost — доставка на удаленный сервер, определяемый по MX записи.

T=… — название использовавшегося транспорта. В наших типовых настройках это:

  • local_delivery — в локальный почтовый ящик
  • remote_smtp — на удаленных сервер.
  • autoreply_pipe — один из автоответчиков
  • address_pipe — передача скрипту через email-alias
  • address_pipe — запись в файл через email-alias

H=… — имя сервера куда была осуществлена доставка по smtp
[…] — IP адрес этого сервера

Вторая строка вашего примера говорит о том, что это сообщение практически сразу было доставлено в локальный почтовый ящик alexey, соответствующий адресу alexey@interost.ru.

Третья строка отмечает дату и время завершения обработки письма.

Также бывают строки с записями об ошибке:

В строках с знаком ’==’ и ’**’:
адрес получателя

R=… — роутер
далее идет текст ошибки

Записи без идентификатора сообщения после даты и времени — это обычно ошибки при приеме сообщения. В них может быть следующая информация:
H=(…) — аргумент SMTP команды HELO или EHLO
F=<…> — адрес отправителя
[…] — сервер с которого производилась отправка далее идет текст ошибки.

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

Внимание! Этот мануал описывает то, как настроить SMTP сервер (сервер отправки писем), отправить письмо через который можно только с того же сервера (то есть с localhost). При этом не будет требоваться никакой авторизации! Будьте внимательны.

lamp-server:~# apt-get install exim4
lamp-server:~# dpkg-reconfigure exim4-config
 Отвечаем на вопросы:
 General type of mail configuration: internet site; mail is sent and received directly using SMTP
 System mail name: желательно вписываем сюда обратную зону для вашего IP интерфейса eth0. Либо просто full hostname сервера (mail.debian.pro, например)
 IP-addresses to listen on for incoming SMTP connections: 127.0.0.1
 Other destinations for which mail is accepted: оставляем пустым. Это список локальных доменов — нам он не нужен.
 Domains to relay mail for: если не знаете зачем оно, то оставляйте пустое поле
 Machines to relay mail for: аналогично, если не знаем — оставляем пустым
 Keep number of DNS-queries minimal (Dial-on-Demand)? No
 Delivery method for local mail: неважно что
 Split configuration into small files? Yes
 Ещё могут спросить, кому перенаправлять почту локального админа. Впишите свою почту, например — туда будут отправляться письма от крона.

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

Type Machine handling outgoing mail for this host (smarthost): smtp.yandex.ru:587

прописываем пароль для ящика в файле /etc/exim4/passwd.client:

smtp.yandex.ru:no-reply@yandex.ru:СВОЙ_ПАРОЛЬ

Если   почтовый сервер яндекс ругается, что нужно заполненное поле FROM. Прописываем его в файле /etc/exim4/conf.d/rewrite/00_exim4-config_header:

begin rewrite *@* no-reply@yandex.ru Ffr

Теперь вы можете отправлять письма при помощи апача (чуть позже опишу как настроить) или командой вида echo «Testing Exim» | mail -s Test vlad@debian.pro

Ну и да — не стоит спамить 😉
Так же не используйте этот метод для тех случаев, когда доступ к серверу по ssh (или даже по ftp в каталоги, доступные по http) имеют доступ люди, которые могут начать спамить.

Как ограничить список ящиков, которым можно отправлять письма с сервера

В конце выбираем «Split configuration into small files: yes» — так удобнее будет.

Теперь создаём необходимые нам файлы:

root@server:~# touch /etc/exim4/allowed.domains; touch /etc/exim4/allowed.mails
 root@server:~# touch /etc/exim4/conf.d/router/01_exim4-outgoing-filter

В файл /etc/exim4/conf.d/router/01_exim4-outgoing-filter пишем правила, которые будут применяться к исходящей почте:

check_outgoing_from_header:
 driver = redirect
 domains = ! +local_domains
 condition = ${if !match {$header_from:}{$sender_address}}
 allow_fail
 data = :fail: You can not send mail from here with From: $header_from as sender: $sender_address
check_outgoing:
 driver = redirect
 domains = ! +local_domains
 senders = ! : ! *@lsearch;/etc/exim4/allowed.domains : ! lsearch;/etc/exim4/allowed.mails
 allow_fail
 data = :fail: You can not send mail from this mailbox from this server.

Если вы всё же выбрали «Split configuration into small files: no», то эти правила нужно вписать сразу после строчки

begin routers

в конфиге exim.

Это правило позволит отправлять только почту с любых ящиков доменов, которые перечислены в файле /etc/exim4/allowed.domains, или ящиков, перечисленных в файле /etc/exim4/allowed.mails. Обратите внимание на «или» — если домен написан в первом файле, то во втором смысле перечислять его ящики нет смысла. А если вам нужно разрешить отправку только с одного ящика домена — то не нужно писать его в allowed.domains, нужно написать конкретный ящик в allowed.mails

Ящики и домены нужно писать целиком (без регулярок, звездочек и прочего) по одному на строчку:

root@server:~# cat /etc/exim4/allowed.domains
 adminunix1.ru
 adminunix2.ru
 root@server:~# cat /etc/exim4/allowed.mails
 noreply@adminunix3.ru
 robot@adminunix3.ru
 webmaster@adminunix3.ru

Проверить можно так:

root@server:~# echo test | sendmail -f noreply@somepieceofshit.com youremail@adminunix.ru

где noreply@somepieceofshit.com — адрес отправителя, а youremail@adminunix.ru — адрес получателя.

В /var/log/exim4/mainlog в ответ на это вы увидите что-то в духе:

2014-11-20 17:10:47 1VphsU-0007JA-Vr ** youremail@adminunix.ru R=check_outgoing: You can not send mail from this mailbox from this server.

Как работают эти правила. Для начала стоит упомянуть, что у писем есть 2 важных заголовка — smtp.sender и header From:. smtp.sender, по сути, smtp-аккаунт, с которого происходит отправка письма. Поле From может содержать произвольную чушь, в том числе и совершенно левый ящик. Например, можно отправить письмо с smtp-аккаунта blah@someshit.com, но в поле From поставить admin@gmail.com. Чтобы посмотреть, кто реально отправил письмо — нужно будет лезть в его исходники. Большинство почтовых провайдеров при несовпадении этих полей кладёт такое письмо в спам. А спамеры, в свою очередь, шлют тонны писем с несовпадающими заголовками. Кхе.
Собственно, правило check_outgoing_from_header проверяет, чтобы в заголовке From содержалось имя smtp-аккаунта. Тут стоит упомянуть, что заголовок From: в нормальном письме выглядит примерно так — «inkvizitor68sl <root@vlad.pro>» (то есть помимо ящика содержит и имя/фамилию отправителя/ник или какую-нибудь другую чушь, которую он соизволит вписать туда). Именно поэтому, полагаться здесь на точное совпадение полей нельзя.

Второе правило (check_outgoing) проверяет, что значение поля sender (он же — smtp.sender, он же — smtp.name) подходит под одно из трех правил. Первое — sender пустой (сюда входят письма, сгенерированные самим почтовым сервером — например, отлупы о недоставке писем). Второе — sender совпадает с шаблоном *@любойдоменизспискаallowed.domains. Третье — поле sender целиком (пользователь@домен) указано в allowed.mails.

Так же учитывайте, что строчка в конфиге apache2 для вхоста вида:

php_admin_value sendmail_path "/usr/sbin/sendmail -t -i -f noreply@adminunix.ru"

выставляет значения поля sender в noreply@adminunix.ru (при том обойти это из самих скриптов уже не получится, только через htaccess). Поэтому, если ваша CMS шлет письма от ящика, отличного от указанного в этом месте — письма слать она перестанет.

Само собой, такая защита обходится (достаточно начать рассылать спам от «доверенных» ящиков) — авторизации всё ещё не требуется. Но мы можем в любой момент выключить ящик до того момента, пока не разберемся, что послужило источником спама на сервере.

В файле конфигурации php поправим sendmail_path.

В Debian: /etc/php5/apache2/php.ini или /etc/php4/apache2/php.ini

< в других дистрибутивах >

sendmail_path = /usr/sbin/exim4 -t

Правильная настройка SPF

Если кратко, то SPF — это способ борьбы со спамом.

Мы собираемся отправлять почту с сервера, PTR IP которого не равен одной из MX-записей сервера, а так же в большинстве случаев PTR IP не равен самому нашему домену (не всегда хостеры соглашаются менять PTR). В этом случае вероятность попадания писем в спам повышается. Но есть хороший способ ее понизить: указать правильно запись SPF нашего домена.

SPF-запись — это обыкновенная запись доменной зоны, имеющая тип TXT. Узнать текущее ее значение для домена можно с помощью команды host в Linux:

$ host -t TXT adminunix.ru
 adminunix.ru TXT record currently not present

В данном примере SPF-запись не задана. Зададим ее. С моего домена почта может отправляться с серверов Gmail и с моего сервера. Для начала узнаем, какой PTR моего сайта (adminunix.ru):

$ nslookup adminunix.ru
 Server:      194.224.52.4
 Address:     194.224.52.4#53
 Non-authoritative answer:
 Name:     adminunix.ru
 Address:  93.174.6.118

IP-адрес моего сервера 93.174.6.118. Узнаем PTR:

$ nslookup 93.174.6.118
 Server:      194.224.52.4
 Address:     194.224.52.4#53
 Non-authoritative answer:
 118.6.174.93.in-addr.arpa name = server.adminunix.ru.

Видно, что PTR IP, к которому привязан мой домен (IP моего сервера) — server.adminunix.ru.

v=spf1 a mx ptr include:_spf.google.com ~all

По порядку:

v=spf1 — версия SPF (первая);
a — разрешение отправлять почту с IP, указанного в A-записи домена (собственно с сервера, на который ваш домен ссылается);
mx — разрешение отправлять почту с IP, указанных в MX-записях домена (в нашем случае сервера Gmail);
ptr — разрешение отправлять почту с IP, PTR-запись которых содержит ваш домен (т.е. сам домен и поддомены);
include:_spf.google.com — подключение разрешений для серверов отправки почту Gmail (совсем не обязательно почта будет слаться с серверов, указанных в MX-записи);
~all — нейтральная реакция на всю остальную почту; здесь можно указать -all, что будет значить, что почта, не попадающая под эти правила, — спам.
Если вы хотите отправлять почту с сервера, не попадающего под все эти правила, его можно указать по IP или домену PTR, например:

v=spf1 a mx ptr ptr:example.com include:_spf.google.com ~all

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

adminunix.ru.      TXT      v=spf1 a mx ptr include:_spf.google.com ~all

После обновления зоны host выдаст следующее:

$ host -t TXT adminunix.ru
adminunix.ru      TXT      »v=spf1 a mx ptr include:_spf.google.com ~all»

PHP mail ()

После всей этой настройки функция mail () в PHP начнет слать почту через ваш локальный сервер на законных основаниях для антиспам-ботов. Но косяк будет в том, что в поле отправителя будет фигурировать адрес системного пользователя www-data@localdomain. Нас это не устраивает. Чтобы почта правильно слалась из mail (), необходимо использовать ее дополнительный параметр.

bool mail ( string $to , string $subject , string $message [, string $additional_headers [, string $additional_parameters ]] )

Именно $additional_parameters нас и интерисует. В него надо передавать реального отправителя:

mail ($to, $subject, $message, $additional_headers, $additional_parameters.» -frealsender@adminunix.ru»);

Указывается отправитель слитно с параметром -f.

Теперь отправленные через mail () письма будут абсолютно адекватны (при условии, что вы указываете все нужные SMTP-заголовки, вроде “FROM:”, “TO:” и т.д.).

А если несколько сайтов с разными IP (настройка Exim для отправки писем с разных IP)?

Мы хотим использовать локальный SMTP-сервер для отправки почты со всех сайтов на сервере. Никаких проблем нет, если настроен Exim правильно (см. выше). Но проблема появляется, если разные сайты работают на разных IP. Мы не хотим в почте «палить» то, что все наши сайты живут на одном сервере. Но Exim по умолчанию шлет всю почту с основного (первого) IP сетевого интерфейса, а этот IP всем получателям в SMTP-заголовках “Received:” письма. Кроме того, там указывается и имя сервера, которые мы в случае с разными сайтами на сервере выбрали нейтральными.

Чтобы не «палить» IP сервера, нужно отсылать письмо на удаленный сервер с IP, равного A-записи домена сайта. Делается это несложно путем изменения конфига Exim. Внесем изменения в настройки транспорта SMTP Exim. Если вы выбрали монолитный конфиг, то нужно отредактировать файл:

# nano /etc/exim4/exim4.conf.template

local_interfaces = a.a.a.a : b.b.b.b : c.c.c.c : d.d.d.d
smtp_active_hostname = ${lookup{$interface_address}lsearch{/etc/exim4/domain2ip}{$value}}
smtp_banner = «$smtp_active_hostname ESMTP $tod_full»

#mcedit /etc/exim4/conf.d/transport/30_exim4-config_remote_smtp

Находим в файле строку “remote_smtp:” (поиск в nano — F6). Добавляем в конец этого блока:

interface = «${lookup{$sender_address_domain}lsearch{/etc/exim4/domain2ip}{$value}}»
helo_data = «$sender_address_domain»

Это значит, что при отправке письма нужно определить домен отправителя почты (для sender@adminunix.ru это adminunix.ru) и отправить почту с IP, к которому этот домен привязан. Само собой разумеется, что домен должен быть привязан к серверу, где установлен Exim.

Так же нужно создать файл в любом месте файл привязки доменов к IP (у домена может быть несколько IP, так что просто lookup-ить его не прокатит). Я выбрал для файла место: /etc/exim4/domain2ip

# nano /etc/exim4/domain2ip

Туда вводим наши домены по шаблону:

adminunix.ru: 123.123.123.123
vasya.ws: 123.123.123.124

Не забудьте дописать домен в файл в случае появления нового сайта.
Кстати, строку helo_data = «$sender_address_domain» можно добавить в файл даже если у вас один IP на все сайты. Тогда в команде HELLO SMTP-протокола (а, следовательно, и в заголовках писем) будет фигурировать ваш домен.

Идея с указанием интерфейса взята отсюда: http://www.directadmin.com/forum/showthread.php?t=36468

Проверка

Остается проверить, чтобы все ваши настройки работали верно. Для этого просто отправим письмо с локального сервера через консоль.

$ mail -a «From:feedbee@adminunix.ru» -s Test feedbee@gmail.com — -ffeedbee@adminunix.ru
Test
Cc:

Проверяем отосланное письмо в ящике получателя:

А вот текст SMTP-протокола:

Delivered-To: feedbee@gmail.com
 Received: by 10.236.109.139 with SMTP id s11cs13826yhg;
 Wed, 24 Nov 2010 02:18:14 -0800 (PST)
 Received: by 10.227.145.134 with SMTP id d6mr9025492wbv.195.1290593893066;
 Wed, 24 Nov 2010 02:18:13 -0800 (PST)
 Return-Path: feedbee@adminunix.ru
 Received: from adminunix.ru (server.adminunix.ru [93.174.6.118])
 by mx.google.com with ESMTP id b7si11085685wer.164.2010.11.24.02.18.12;
 Wed, 24 Nov 2010 02:18:12 -0800 (PST)
 Received-SPF: pass (google.com: domain of feedbee@adminunix.ru designates 93.174.6.118 as permitted sender) client-ip=93.174.6.118;
 Authentication-Results: mx.google.com; spf=pass (google.com: domain of feedbee@adminunix.ru designates 93.174.6.118 as permitted sender) smtp.mail=feedbee@adminunix.ru
 Received: from root by server.adminunix.ru with local (Exim 4.69)
 (envelope-from <feedbee@adminunix.ru>)
 id 1PLCQW-0006KD-Pc
 for feedbee@gmail.com; Wed, 24 Nov 2010 10:18:12 +0000
 To: feedbee@gmail.com
 Subject: Test
 From:feedbee@adminunix.ru
 Message-Id: E1PLCQW-0006KD-Pc@server.adminunix.ru
 Date: Wed, 24 Nov 2010 10:18:12 +0000

Test

P.S. Чтобы отправленная почта не попадала в спам, отправляйте письма только от имени реально существующих на серверах Gmail адресов на ваших доменах. Туда же повалятся уведомления о недоставках.

Чтобы при отправке писем root'у, как это любят делать многие утилиты (например smartd), письмо уходило не на root@example.org, а на admin@adminunix.ru. Я изменил /etc/aliases:

# cat /etc/aliases
 # /etc/aliases
 mailer-daemon: postmaster
 postmaster: root
 nobody: root
 hostmaster: root
 usenet: root
 news: root
 webmaster: root
 www: root
 ftp: root
 abuse: root
 noc: root
 security: root
 root: admin@adminunix.ru

В файл /etc/exim4/conf.d/rewrite/00_exim4-config_header пишем правила,

root@example.org admin@adminunix.ru rTbtc

перезапускаем exim

service exim4 restart
 # exim -brw root
 sender: root@example.org
 from: root@example.org
 to: admin@adminunix.ru
 cc: admin@adminunix.ru
 bcc: admin@adminunix.ru
 reply-to: admin@adminunix.ru
 env-from: admin@adminunix.ru
 env-to: admin@adminunix.ru

А для затирания Received из заголовков писем с ip серверов которые коннектятся к нашему почтовику надо добавить вот эту строчку:

/etc/exim4/conf.d/transport/30_exim4-config_remote_smtp_smarthost

headers_remove = Received

Все, что вы хотели узнать о тонкостях настройки Spamassassin

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

Пакет Spamassassin – один из самых популярных инструментов для борьбы со спамом, свободно распространяемый под лицензией Apache. Будучи написанным на языке Perl, он имеет высокий уровень переносимости и наверняка будет работать на любой UNIX-подобной операционной системе. Этим же обусловлена и относительная медлительность этого фильтра. В данной статье будет рассмотрено использование Spamassassin на FreeBSD, однако основные принципы работы сохранятся неизменными и на других платформах.

Тактика и используемые системы вооружения

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

Таблица 1. Примеры характерных признаков спама

ПравилоОписаниеБалл
HEAD_LONGЗаголовок сообщения слишком длинный2,5
REPLY_TO_EMPTYПоле заголовка «Replay-To» пустое1,274
SUBJ_YOUR_FAMILYТема сообщения содержит фразу «Your Family»1,648
ALL_TRUSTEDСообщение передавалось только через доверенные узлы-2,4

Spamassassin также может проверять принадлежность адреса отправителя одному или нескольким блок-листам реального времени (RBL). Опять-таки результат такой проверки лишь добавит баллы в общую копилку.

Рассматриваемый фильтр умеет взаимодействовать и с системами, основанными на сигнатурном анализе (Razor, Pyzor, DCC). По умолчанию включен только Pyzor, поскольку DCC не является открытой системой, а сервис Razor полностью бесплатен только в случае персонального использования.

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

Развертывание комплекса на местности

Установка выполняется традиционно: на FreeBSD лучше всего воспользоваться коллекцией портов; пользователи Linux могут установить Spamassassin из исходных кодов либо поискать в сети готовый прекомпилированный пакет для своего дистрибутива. Более того, поскольку Spamassassin разработан на Perl, его можно установить непосредственно из коллекции CPAN, как и любой другой Perl-модуль:

root# perl -MCPAN -e shell

cpan> o conf prerequisites_policy ask

cpan> install Mail::SpamAssassin

cpan> quit

Далее мы будем предполагать, что пакет устанавливается из коллекции портов:

# cd /usr/ports/mail/p5-Mail-SpamAssassin

# make

# make install

Вместе с командами make и make install вы можете указать ряд дополнительных параметров (см. таблицу 2).

Таблица 2. Некоторые опции, полезные при инсталляции

Назначение параметраКлюч для make
Отключить поддержку SSL-DWITHOUT_SSL
Включить поддержку MySQL-DWITH_MYSQL
Включить поддержку PostgreSQL-DWITH_PGSQL
Включить поддержку сигнатурного анализатора Vipul’s Razor-DWITH_RAZOR
Включить поддержку запросов SPF-DWITH_SPF_QUERY
Использовать Yahoo DomainKeys-DWITH_DOMAINKEYS
Использовать базу IP-адресов с географической привязкой-DWITH_RELAY_COUNTRY
Устанавливать вспомогательные инструменты-DWITH_TOOLS

Замечание: при первой установке из коллекции портов вы получите представленное на рис. 1 диалоговое окно, где сможете отметить нужные параметры визуально, без ввода дополнительных параметров в командной строке. Ваш выбор будет сохранен в /var/db/ports/p5-Mail-SpamAssassin/options, и при последующих установках (например, при обновлении версии пакета) вы уже не будете получать этот диалог.

Рисунок 1. Конфигурационный диалог

Поясню смысл приведенных выше опций.

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

Если вы планируете использовать байесовый анализатор, то поддержка MySQL или PostgreSQL позволит вам хранить статистические данные, накапливаемые анализатором, в базе данных. Кроме того, в БД могут храниться настройки пользователей и автоматически формируемый «белый» список. Если ни одна из СУБД не поддерживается, будут использоваться «плоские» файлы.

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

Запросы SPF (Sender Policy Framework, см. http://spf.pobox.com) позволяют использовать систему DNS для проверки того, является ли IP-адрес источника сообщения легитимным SMTP-сервером. Для SMTP-серверов администратор размещает в соответствующей зоне DNS запись типа TXT, информирующую о том, что с данного IP-адреса предусмотрена отправка сообщений электронной почты. Если для адреса источника такая TXT-запись отсутствует, то получатель вправе отклонить запрос на соединение.

Yahoo DomainKeys (см. http://antispam.yahoo.com/domainkeys) действует аналогично SPF, но вместо простой пометки хранит в соответствующей зоне публичный ключ SMTP-сервера, позволяющий верифицировать цифровые подписи получаемых электронных сообщений (которые подписываются автоматически при отправке).

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

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

Если вы выполняете установку вручную, будьте готовы к тому, что в процессе инсталляции придется удовлетворить большое число зависимостей (различные модули Perl). Список необходимых модулей можно найти в файле INSTALL дистрибутива.

Также не забудьте добавить следующую строчку в /etc/rc.conf:

spamd_enable="YES"

Это необходимо для того, чтобы демон Spamassassin мог запускаться из стартового сценария /usr/local/etc/rc.d/sa-spamd.sh.

Дислокация и приведение в полную боевую готовность

По умолчанию (установка из портов, prefix не используется) исполнимые файлы пакета размещаются в /usr/local/bin. Размещение и назначение основных конфигурационных файлов разъясняется в таблице 3.

Таблица 3. Размещение конфигурационных файлов

ФайлНазначение
/usr/local/etc/mail/spamassassin/local.cfОсновной файл конфигурации (общесистемный)
/usr/local/etc/mail/spamassassin/*.cfПрочие рабочие файлы конфигурации
/usr/local/etc/mail/spamassassin/init.preЗагружаемые модули (plugins),  совместимые с версией 3.0
/usr/local/etc/mail/spamassassin/v310.preЗагружаемые модули (plugins), совместимые с новой версией 3.1
/usr/local/share/spamassassin/*.cfКонфигурация по умолчанию
/.spamassassin/*Пользовательские настройки и файлы данных

Обратите внимание, что настоятельно не рекомендуется вносить изменения в файлы, размещаемые в каталоге /usr/local/share/spamassassin, поскольку они будут перезаписаны при обновлении версии пакета, и вы потеряете все свои настройки. Если вам нужно что-то изменить, просто укажите строку с нужными параметрами в рабочем конфигурационном файле в каталоге /usr/local/etc/mail/spamassassin.

Следующие подразделы описывают некоторые наиболее полезные параметры конфигурации.

Настройка набора тестов

  • required_score N – «Порог срабатывания» фильтра, то есть количество баллов, при достижении которого сообщение признается спамом. N – число с плавающей запятой. Значение по умолчанию – 5.0.
  • score <имя_теста> nL [nN nB nBN] – баллы, назначаемые тесту <имя_теста>. Может быть указано одно значение (общее) или четыре: nL – локальный балл, nN – при работающих сетевых тестах, nB – при включенном байесовом анализаторе, nBN – при работающих сетевых тестах и статистическом анализаторе.

Имена тестов и значения по умолчанию можно узнать в файле /usr/local/share/spamassassin/50_scores.cf. Чтобы полностью отключить какой-либо тест, присвойте ему значение 0.0.

Сами тесты (как правило – регулярные выражения) находятся в этом же каталоге в других cf-файлах. При желании вы можете создавать и свои проверки по аналогии с имеющимися. Как вы можете увидеть, для этого существует несколько групп правил (header, body, rawbody, meta, uri и др.).

Подробно синтаксис правил описывается на странице справки perldoc Mail::SpamAssassin::Conf.

Белые и черные списки

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

Для этого существует группа параметров, определяющих «белые» и «черные» списки:

  • whitelist_from <адрес_или_шаблон> – отправители, почтовый адрес которых соответствует шаблону, рассматриваются как доверенные, и почта от них не подвергается проверке на спам. Под шаблоном в данном случае понимается запись в стиле командной строки, где символ «*» обозначает любое количество символов, «?» – любой один символ. Например, «*@contora.ru» занесет в «белый» список всех пользователей домена contora.ru.
  • blacklist_from <адрес_или_шаблон> – аналогично «белому» списку, но теперь отправитель априори рассматривается как спамер, и все письма от него помечаются как спам без дальнейшего анализа.
  • whitelist_to <адрес_или_шаблон> – все сообщения на указанный адрес будут передаваться без фильтрации. Можно использовать, если владелец адреса желает получать всю почту, адресованную ему. Также рекомендуется устанавливать этот параметр для адреса abuse, чтобы даже в случае неправильной настройки фильтра с вами можно было связаться.
  • blacklist_to <адрес_или_шаблон> – все сообщения на указанный адрес будут рассматриваться как спам. Например, таким образом можно организовать «прививки» для статистического анализатора, создав специальный адрес для спама и максимально «засветив» его на просторах Интернета (при этом должно быть включено автообучение, см. ниже).

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

Опции сетевых проверок

Фильтр Spamassassin умеет проводить ряд сетевых тестов, таких как проверка на принадлежность адреса отправителя доверенной сети, поиск IP-адреса в списках RBL, и т. п.

Некоторые параметры, которые вы можете использовать в своем конфигурационном файле, приведены ниже:

  • trusted_networks <список_сетей> – перечисленные здесь сети (в формате CIDR, например: 12.34.56.78/24) будут рассматриваться как доверенные.
  • skip_rbl_checks 1 | 0 – этим правилом вы можете отключить (значение 1) проверку на принадлежность адреса отправителя спискам RBL. Это может быть полезно, если такие проверки вы предпочитаете выполнять другими средствами (например, с помощью spamd или непосредственно правилами MTA), а также если риск потери легальных сообщений для вас неприемлемо высок.

Параметры обучения статистического анализа

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

Некоторые параметры:

  • use_bayes 1 | 0 – включает использование статистического анализатора.
  • bayes_auto_learn 1 | 0 – разрешает автообучение фильтра, в ходе которого письма, признанные спамом либо набравшие минимальный балл, автоматически обрабатываются для обучения анализатора как спам (spam) или не спам (ham) соответственно.
  • bayes-ignore-header <тэг_заголовка> – не анализировать письма, содержащие указанный тэг в заголовке. Может оказаться полезным для отмены повторного анализа уже обработанных (например, вышестоящим провайдером) сообщений.
  • bayes_ignore_from <адрес> – не подвергать анализу письма от указанного адресата.
  • bayes_ignore_to <адрес> – не анализировать сообщения, предназначенные указанному пользователю.

Прочие параметры

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

ok_locales ru en

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

Параметр report_safe указывает на то, что следует делать с оригинальным сообщением, если оно будет признано спамом: либо оставить как есть (значение 0), либо приложить к отчету как вложение (значение 1), либо добавить к отчету как текст (значение 2).

Настройки администратора

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

  • bayes_path <путь_к_базе> – указывает путь к каталогу, в котором будут храниться данные, накапливаемые статистическим анализатором.
  • bayes_file_mode <права_доступа> – задаются права доступа для вновь создаваемых файлов данных анализатора.
  • bayes_sql_* – группа правил для настройки доступа к внешней БД в случае, если она используется для хранения данных анализатора. Подробнее взаимодействие с СУБД будет рассмотрено в одном из следующих разделов.
  • loadplugin <имя_модуля> [<путь_к_модулю>] – так можно подключить дополнительный модуль.

Вспомогательные скрипты

Если вы устанавливали вспомогательные инструменты, то найти их можно будет в каталоге /usr/local/share/spamassassin/tools. Все они снабжены подробными комментариями или POD-документацией в самом тексте сценария. Здесь я приведу лишь краткое описание некоторых скриптов:

  • sa-stats.pl – формирует статистику работы фильтра на основе почтового лог-файла (по умолчанию /var/log/maillog). Пример вывода сценария:

# ./sa-stats.pl -s 20051013

Report Title     : SpamAssassin — Spam StatisticsReport Date      : 2005-10-13

Period Beginning : четверг, 13 октября 2005 г. 00:00:00

Period Ending    : пятница, 14 октября 2005 г. 00:00:00

Reporting Period : 24.00 hrs

--------------------------------------------------

Note: «ham» = «nonspam»

Total spam detected    :      737 (  54.51%)

Total ham accepted     :      615 (  45.49%)

                        -------------------

Total emails processed :     1352 (   56/hr)

Average spam threshold :       12.00

Average spam score     :       17.85

Average ham score      :        4.66

Spam kbytes processed  :     5255   (  219 kb/hr)

Ham kbytes processed   :    10632   (  443 kb/hr)

Total kbytes processed :    15887   (  662 kb/hr)

Spam analysis time     :     2057 s (   86 s/hr)

Ham analysis time      :     1434 s (   60 s/hr)

Total analysis time    :     3491 s (  145 s/hr)

Statistics by Hour

----------------------------------------------------

Hour                          Spam               Ham

-------------    -----------------    --------------

2005-10-13 00            12 ( 27%)         32 ( 72%)

2005-10-13 01           102 ( 75%)         33 ( 24%)

... ... ... ...

2005-10-13 23             0 (  0%)          0 (  0%)

Done. Report generated in 25 sec by sa-stats.pl, version 6256.

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

  • check_whitelist – проверяет или очищает автоматически сформированный «белый» список, позволяя удалить из него редко используемые адреса.

# ./check_whitelist

-1.4        (-4.3/3)  --  user@myserver.ru|ip=none11.1        (22.2/2)  --  rrryyy@mail.ru|ip=8x.2yy

 0.0         (0.0/2)  --  security-advisories@freebsd.org|ip=216.136

-2.3    (-394.9/171)  --  mailer-daemon@myserver.ru|ip=none

... ... ... ...

Первый столбец показывает средний балл писем от указанного адресата, во втором столбце выводится расшифровка того, как именно этот балл был получен. Обратите внимание, что в качестве IP-адреса используются лишь первые два октета, то есть оценивается только принадлежность отправителя к некоторой сети. Подробнее про автоматический «белый» список рассказано в следующем разделе.

  • convert_awl_dbm_to_sql – преобразует базу «белого» списка в SQL-команды для заливки данных во внешнюю БД.

Подразделение AWL

AWL (Auto White List) – система, используемая в Spamassassin по умолчанию, начиная с версии 3.0. Принцип работы AWL заключается в следующем: для всех отправителей ведется база данных, в которой сохраняется число обработанных сообщений и набранный в сумме балл. При получении письма с адреса, фигурирующего в базе AWL, рассчитывается его «чистый» балл (без учета AWL), а окончательный балл проставляется как производное значение от рассчитанного «чистого» и взятого из базы исторического значения.

Например, если ранее с адреса rrryyy@mail.ru было получено два сообщения, набравших в сумме 22.2 балла (см. листинг в предыдущем разделе, поясняющий работу утилиты check_whitelist), и приходит третье письмо с «чистым» баллом 1.8, то итоговый балл будет равняться:

St = (Th / Ch — Sc) * f + Sc = (22.2 / 2 — 1.8) * 1 + 1.8 = 11.1

где:

  • St – итоговый балл;
  • Th – суммарный «исторический» балл;
  • Ch – количество «исторических» писем;
  • Sc – «чистый» балл текущего письма (без учета AWL);
  • – весовой коэффициент системы AWL.

Таким образом, система AWL учитывает «кредитную историю» отправителя, доверяя в большей степени тем, кто в прошлом вел себя хорошо.

Отключить использование AWL можно, указав в конфигурационном файле следующую строку:

use_auto_whitelist 0

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

auto_whitelist_factor 0.5

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

Взаимодействие с MTA

SpamAssassin может быть подключен практически ко всем популярным почтовым серверам: Sendmail, Postfix, Qmail, Exim, Courier-MTA, Communigate Pro и некоторым другим. Подробные инструкции можно получить на странице http://wiki.apache.org/spamassassin/IntegratedInMta.

Для работы с Sendmail Spamassassin обычно подключается через milter. В сети можно найти несколько «мильтеров» для работы со Spamassassin.

Мы будем использовать имеющийся в коллекции портов spamass-milter:

# cd /usr/ports/mail/spamass-milter-0.3.0

# make install

После установки нужно будет добавить в /etc/rc.conf строку для автоматического запуска spamass-milter при загрузке системы:

spamass_milter_enable="YES"

Наконец, добавляем поддержку этой программы в конфигурационный mc-файл Sendmail (обычно соответствует доменному имени сервера, например /etc/mail/myserver.ru.mc):

MAIL_FILTER (`spamassassin’, `S=local:/var/run/spamass-milter.sock, F=, T=C:15m;S:4m;R:4m;E:10m’) dnl

define (`confINPUT_MAIL_FILTERS’, `spamassassin’) dnl

Если вы используете и другие фильтры (например, clmilter из пакета ClamAV), то перечислите их в одной строке «confINPUT_MAIL_FILTERS», поскольку такая запись должна быть только одна.

Как вариант, вместо строк MAIL_FILTER можно использовать INPUT_MAIL_FILTER. В этом случае второе определение не потребуется.

Теперь осталось пересобрать cf-файл, запустить Spamassassin и spamass-milter и перезагрузить Sendmail:

# cd /etc/mail

# make

# make install

# /usr/local/etc/rc.d/sa-spamd.sh start

# /usr/local/etc/rc.d/spamass-milter.sh start

# make restart

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

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

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

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

:0fw: spamassassin.lock

* < 256000

| spamassassin

# Все сообщения с X-Spam-Status = Yes помещаем в карантин

:0:

* ^X-Spam-Status: Yes

carantine

Если у вас запущен демон spamd, то вместо вызова spamassassin лучше использовать клиент spamc, который будет обращаться к находящемуся в памяти серверу. Это позволит избежать запуска отдельного экземпляра скрипта для обработки каждого входящего сообщения.

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

Дальнейшая участь спама

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

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

На странице http://wiki.apache.org/spamassassin/SpamQuarantine предлагается два других решения: использование веб-интерфейса Maia Mailguard и программы SpamAssassin Quarantine (SAQ). Чтобы не перегружать статью, оставлю их вам для самостоятельного изучения (возможно, об особенностях этих программ мы поговорим в другой раз).

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

Проверка боеготовности и обучение личного состава

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

X-Spam-Status: No, score=-0.7 required=12.0 tests=ALL_TRUSTED,AWL,    MAILTO_TO_SPAM_ADDR,NO_REAL_NAME autolearn=ham version=3.1.0
X-Spam-Checker-Version: SpamAssassin 3.1.0 (2005-09-13) on myserver.ru

Из этого заголовка видно следующее: сообщение было обработано фильтром Spamassassin, запущенным на вашем сервере (тэг X-Spam-Checker-Version). Письмо не было признано спамом (No), набрало -0.7 балла при необходимых 12.0, положительный результат был дан перечисленными после tests тестами. Автоматическое обучение статистического фильтра было выполнено для этого письма в режиме ham (не спам).

Таким образом, можно считать, что фильтр работает.

Для писем, признанных спамом, будет формироваться отчет (пример приведен на рис. 2). Текст сообщения можно изменять в настройках фильтра (используются строки report в конфигурационном файле). Помимо текста, извещающего пользователя, что сообщение было признано спамом, ниже дается подробная расшифровка того, какой тест сколько баллов внес в итоговый результат. Подобная детализация очень полезна для анализа причин ложного срабатывания, если оно произойдет. Оригинальное сообщение по умолчанию прикладывается к отчету как вложение (это поведение можно настроить с помощью параметра конфигурации report_safe).

Рисунок 2. Так для пользователя выглядит спам

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

После того как будет накоплена достаточная база, в заголовках обработанных писем будет появляться и информация о выполнении тестов BAYES_xx:

X-Spam-Status: Yes, score=14.9 required=12.0 tests=BAYES_99,EXTRA_MPART_TYPE,    FORGED_OUTLOOK_TAGS,FORGED_RCVD_HELO,HTML_IMAGE_ONLY_16,HTML_MESSAGE,

    RCVD_IN_NJABL_DUL,RCVD_IN_SORBS_DUL,RCVD_NUMERIC_HELO,

    SUBJECT_ENCODED_TWICE autolearn=no version=3.1.0

X-Spam-Level: **************

X-Spam-Checker-Version: SpamAssassin 3.1.0 (2005-09-13) on myserver.ru

Как видите, для этого сообщения байесовый тест дал результат от 99 до 100% вероятности того, что письмо – спам. Совместно с другими тестами письмо набрало 14.9 баллов, что позволило отнести его к спаму, несмотря на достаточно высокий порог срабатывания.

Основываясь на личном опыте использования фильтра, могу сказать, что сразу после установки (поскольку дело было на работающем сервере, то необходимый порог срабатывания был на период тестирования установлен на достаточно высоком уровне – 12 баллов) Spamassassin стал отмечать примерно половину приходящего спама. Специального обучения статистического анализатора я не проводил, целиком полагаясь на самообучение. Спустя сутки фильтр накопил достаточную базу и стал учитывать результаты байесовой классификации. При этом точность срабатывания возросла примерно до 91%. Ложных срабатываний пока не наблюдалось.

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

# sa-learn --spam ~serg/sa/spams

Learned tokens from 20 message (s) (20 message (s) examined)

# sa-learn --ham ~serg/sa/hams

Learned tokens from 5 message (s) (5 message (s) examined)

Последним параметром указывается либо файл (в формате mailbox), либо каталог, содержащий примеры писем (например, в формате msg). Нужно заметить, что обучение может выполняться довольно долго (у меня обработка 25 сообщений заняла почти минуту).

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

После обучения вы можете просмотреть дамп базы:

# sa-learn –dump

0.000   0          3          0  non-token data: bayes db version0.000   0       2792          0  non-token data: nspam

0.000   0        623          0  non-token data: nham

0.000   0     131028          0  non-token data: ntokens

0.000   0 1010692073          0  non-token data: oldest atime

0.000   0 1129590682          0  non-token data: newest atime

0.000   0 1129530349          0  non-token data: last journal sync atime

0.000   0          0          0  non-token data: last expiry atime

0.000   0          0          0  non-token data: last expire atime delta

0.000   0          0          0  non-token data: last expire reduction count

0.049   0          1 1129026204  91a35b559c

0.958   1          0 1129026743  92485c309a

0.049   0          1 1129028552  f92317eba2

... ... ... ... ...

К процессу обучения можно приобщить и пользователей. Создайте специальные почтовые ящики для спама и не спама (например, sa-spam@myserver.ru и sa-ham@myserver.ru) и проинструктируйте своих пользователей на первый из них пересылать пропущенный спам (так называемый false negative), на второй – хорошие сообщения, ошибочно признанные спамом (false positive).

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

Второй путь – настроить procmail на обработку таких писем, что называется, на лету (пример взят со страницы http://wiki.apache.org/spamassassin/ProcmailToForwardMail):

:0

* ^To:.*spam@example.com

   {

   * < 256000

   :0c: spamassassin.spamlock

   | sa-learn --spam

   :0: spamassassin.filelock

   spam

   }

Здесь помимо инициализации обучения для поступающих писем их копии также сохраняются в папке spam, которая может пригодиться в будущем для ручного обучения фильтра.

Подробнее о режимах обучения смотрите страницу справочного руководства man sa-learn и соответствующие Wiki-страницы.

Усиление за счет внешней СУБД

По умолчанию Spamassassin хранит данные (автоматически формируемый «белый» список, историю статистического анализатора) в отдельных файлах в формате DBM. Для повышения производительности можно перенести их во внешнюю базу данных. Spamassassin умеет работать с MySQL и PostgreSQL (поддержка СУБД должна быть включена на этапе установки пакета). Рассмотрим настройку для работы с базой PostgreSQL.

Сначала вам нужно будет подготовить базу данных для работы. Саму БД придется создать вручную, а заодно и пользователя, который будет владельцем нашей базы. А поскольку Spamassassin использует хранимые процедуры на языке PL/pgSQL, то также потребуется подключить и язык программирования к вновь созданной базе:

# createuser --no-adduser --no-createdb -U pgsql sauser

# createdb --owner sauser -U pgsql sabase

# createlang -U pgsql plpgsql sabase

Замечание: pgsql – имя администратора PostgreSQL, который имеет право создавать базы и пользователей, sauser – вновь создаваемый пользователь-владелец БД Spamassassin, sabase – база данных Spamassassin.

Далее нужно сформировать правильную структуру БД, для чего воспользуемся готовыми SQL-сценариями, которые можно будет найти в каталоге sql распакованного дистрибутива (при установке из портов это будет каталог /usr/ports/mail/p5-Mail-SpamAssassin/work/Mail-SpamAssassin-3.1.0/sql):

# psql -d sabase -U sauser -e < bayes_pg.sql

CREATE TABLE bayes_expire (

  id integer NOT NULL default «0»,

  runtime integer NOT NULL default «0»

) WITHOUT OIDS;

CREATE TABLE

CREATE INDEX bayes_expire_idx1 ON bayes_expire (id);

... ... много команд ... ...

CREATE FUNCTION

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

bayes_store_module Mail::SpamAssassin::BayesStore::PgSQL

bayes_sql_dsn DBI:Pg:dbname=sabase;host=localhost

bayes_sql_username sauser

bayes_sql_password ""

Если у вас уже накоплена статистическая база в формате DBM, то перенести их в СУБД можно следующим образом. Перед тем как менять настройки в конфигурационном файле, сделайте резервную копию базы:

# sa-learn --backup > sabase.back

После того как настройки будут изменены для работы с СУБД, восстановите данные из сформированной резервной копии:

# sa-learn --restore sabase.back

Поскольку формат резервной копии не зависит от используемого модуля базы данных, то sa-learn самостоятельно выполнит конвертирование данных в соответствии с используемой базой данных.

Также поддерживается хранение во внешней БД пользовательских настроек и «белых» списков. Для подготовки таблиц нужно выполнить следующие команды:

# psql -d sabase -U sauser -e < userpref_pg.sql

# psql -d sabase -U sauser -e < awl_pg.sq

А в конфигурационном файле указать аналогичные приведенным выше опции подключения к базе данных:

user_scores_dsn DBI:Pg:dbname=sabase;host=localhost

user_scores_sql_username sauser

user_scores_sql_password ""

user_awl_dsn DBI:Pg:dbname=sabase;host=localhost

user_awl_sql_username sauser

user_awl_sql_password ""

Дополнительные сведения можно получить из файлов README.* в указанном выше каталоге sql.

Индивидуальный защитный комплект

Spamassassin может быть установлен и для персонального использования без необходимости иметь права администратора системы. Например, если у вас есть учетная запись на сервере, то сможете установить Spamassassin в своем домашнем каталоге и настроить его на проверку почты с помощью procmail. В этом случае вы сможете настроить фильтр именно так, как хотите, не обращаясь к системному администратору сервера. Прежде чем вы установите Spamassassin в свой домашний каталог, вам потребуется указать в ваших переменных окружения пути к модулям и библиотекам Perl, если это не было сделано ранее. Должны быть определены переменные PATH, MANPATH, PER5LIB и LANG.

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

# perl Makefile.PL PREFIX=$HOME && make && make install

Далее внесите в ваш файл .forward такую строчку:

«|IFS=» « && exec /usr/bin/procmail -f- || exit 75 #user»

Это приведет к перенаправлению всей вашей почты на procmail, который должен быть настроен на обработку спама (пример см. выше, использовать следует пользовательский конфигурационный файл .procmailrc). Пример конфигурационного файла для procmail можно найти в дистрибутиве под именем procmailrc.example. Не забывайте теперь вызывать нужные программы, указывая путь к файлам, установленным в вашем домашнем каталоге (или укажите нужный каталог в вашей переменной окружения PATH). Подробности смотрите на странице http://wiki.apache.org/spamassassin/SingleUserUnixInstall.

Враг будет разбит!

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

Приложение

Справка

Пакет Spamassassin был разработан Джастином Мэйсоном (Justin Mason) на базе кода программы filter.plx. Весной 2001 года проект был выложен на сайте Sourceforge.net. В настоящее время Spamassassin разрабатывается силами Apache Software Foundation и начиная с версии 3.0 выпускается под лицензией Apache. Spamassassin лежит в основе ряда других антиспамовых решений, например McAfee SpamKiller.

Управление Exim

Пуск/Остановка/Рестарт Exim

/etc/init.d/exim start|stop|restart
После того как вы внесли изменения в файл конфигурации, необходимо перезапустить exim, или послать рабочему процессу сигнал SIGHUP, что-бы он перечитал конфигурационный файл и изменения вступили в силу. Предпочтительней естественно отправить сигнал, нежели перезапускать приложение.
kill -HUP `cat /var/run/exim.pid`

Чем в данный момент занят MTA Exim?

exiwhat

Проверка маршрутизации почты по адресу электронной почты

exim -bt email@example.com

Генерирование и отображение статистики Exim из лог-файла

eximstats /path/to/exim_mainlog

Проверка SMTP содинения из коммандной строки для определенного IP-адреса. Результат покажет через какие проверки будет проходить письмо с данного IP-адреса, через какие ACL и фильтры. Необходимо заменить x.x.x.x на необходмый IP-адрес.

exim -bh x.x.x.x

выводит все значения установленные в конфиге. У этой команды тоже есть
куча параметров, но дефолтное использование + grep достаточно в 90%
случаев.

exim -bP

Посмотрим настройки транспорта

exim -bP transports

Посмотрим настройки транспорта и подписи DKIM

exim -bP transports|grep dkim

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

Например exim -bd -d запускает exim как демон, выводя на консоль всю
отладочную информацию. Чтобы уменьшить количество выдаваемой информации,
можно использовать -dd (имеет смысл только с -bd) пропускает информацию
по подпроцессам. Или -v, простое описание того, что делает exim (при
использовании -d включена по умолчанию).

exim -d

кроме того, что выдает версию и некоторую информацию о бинарнике,
проверяет exim.conf на ошибки (А скорее, на опечатки. Если эта опция
говорит, что все хорошо, то это еще не значит, что ВСЁ хорошо).

exim -bV
 exim -F <string>

устанавливает имя отправителя. Если опция не указана, подставляется
значение поля «gecos» из данных пароля пользователя.

 exim -f <address>

устанавливает адрес отправителя. Обычно, она может использоваться только
доверенными пользователями, но директива «untrusted_set_sender» может
разрешить её использование недоверенным пользователям.

Если не понятно, в чем разница между опциями, объясню: приходит письмо
от Vasya Pupkin <admin@server.ru.>.

Vasya Pupkin — это имя отправителя (опция -F)
admin@server.ru — адрес (опция -f)

Информация по очередям(Queue)

Вывести информацию по колличеству писем в очереди

exim -bpc

Вывести список сообщений в очереди (время в очереди, размер, идентификатор сообщения, отправитель, получатель)

exim -bp

Отображение всех сообщений в очереди (количество, объем, старых, новых, области, и итоги)

exim -bp | exiqsumm

Поиск сообщений в очереди

Поиск в очереди сообщения от определенного отправителя

exiqgrep -f [user]@example.com

Поиск в очереди сообщения по размеру, совпадающего с регулярным выражением:

exiqgrep -s `^7..$` [...]

Поиск в очереди сообщений для конкретного получателя/домена

exiqgrep -r [user]@example.com

Вывод только Message-ID, как результат одного из двух поисковых запросов выше

exiqgrep -i [ -r | -f ] ...

Вывод количества сообщений, как результат одного из поисковых запросов выше

exiqgrep -c [ -r | -f ] ...

Вывод только Message-ID очереди

exiqgrep -i

Просмотр сообщений в очереди

Просмотр заголовков сообщения в очереди

exim -Mvh messageID

Просмотр тела сообщения в очереди

exim -Mvb messageID

Просмотр лога сообщения

exim -Mvl messageID

Переместить сообщение (без ошибок)

exim -Mvl messageID

Отправить сообщение об ошибке отправителю письма с формулировкой «отменено администратором»

exim -Mg messageID

Удалить сообщения и не посылать никаких ошибок (в логах упоминание будет).

exim -Mrm messageID

Заблокировать  (заморозить) сообщение:

exim -Mf messageID messageID

Разблокировать  (разморозить) сообщение:

exim -Mt messageID

Добавить получателя в сообщение:

exim -Mar messageID

Редактировать отправителя сообщения:

exim -Mes messageID

Просмотр заголовков сообщения в очереди

exim -Mvh

Просмотр теля сообщения в очереди

exim -Mvb

Просмотр лога сообщения

exim -Mvl

Если сообщение находится в состоянии «попытки доставки», следующие опции
на него не повляют: -Mrm, -Mg, -Mar, -Mes, -Mf, -Mt, -Mmad, -Mmd.

Для сообщений, которые подозреваются в спаме удобно сначала массово,
сделать -Mf, потом -Mvl, -Mvh и -Mvb для пары выбранных наугад
сообщений. Если все еще невозможно с консоли определить спам ли это
(например, проблемы с кодировками или есть вложения), то можно с помощью
— Mar добавить себя в список получателей, и ускорить данное сообщение с
помощью -M. Когда все наконец станет ясно, то либо -Mrm, либо -Mt.

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

Опция -q имеет флаги. Её использование таково exim -q<qflags><time>

Это значит, что вы можете комбинировать её разновидности (в отличие, от,
например -M, где вы НЕ можете указать -Mvlhb, чтобы просмотреть и логи,
и заголовки, и тело сообщения). Тем не менее, флаги должны быть указанны
в правильно порядке.

exim -qq...

двухступенчатое выполнение очереди. При первой обработке очереди опция
«queue_smtp_domains» принимается как совпадающая с каждым доменом.
Адреса роутятся, происходят локальные доставки, но удалённые транспорты
не запускаются. Во время второй обработки происходит нормальное
сканирование очереди. Плюс такого способа в том, что те сообщения
которые роутятся на один и тот же хост, в основном, идут через одно
SMTP-соединение, на основе БД совпадений, которые были установлены при
первом сканировании очереди.

 exim -q[q]i...

если присутствует флаг i то доставляются только те сообщения, для
которых еще не было попытки доставки.

 exim -q[q]f...

если присутствует флаг f, доставляются любые незамороженные сообщения
(независимо от того, пришло их время повтора или нет).

 exim -q[q]ff...

то же что и f, но замороженные сообщения тоже доставляются.

 exim -q[q][f[f]]l

l определяет, что нужно делать только локальные доставки (остальные
сообщения, разумеется, остаются в очереди).

Значение time идет после всех флагов. Он определяет промежуток времени,
через который будет повторяться заданная обработка очереди. Например:

    exim -ffl10m

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

 /usr/exim/bin/exim -bd -q30m

А так можно запустить демона, который будет обслуживать входящие
соединения и обрабатывать очередь каждые 30 минут (собственно штатные
средства ОС, его примерно так и запускают).

Начать процесс выполнения очереди

exim -q -v

Принудительный запуск другой очереди

exim -qf

Доставить сообщение, вне зависимости от состояния блокировки или времени повторной доставки

exim -M messageID

Доставить сообщение, если достигнуто время для доставки

exim -Mc messageID

Принудительный запуск другой очереди c удалением замороженных сообщений

exim -qff

Начать процесс выполнения только для локальных получателей

exim -ql -v

Удалить сообщение из очереди

exim -Mrm messageID

Удалить все сообщения, которые старше, чем Х секунд из очереди (например, 5 дней будет 432 000 секунд)

exiqgrep -o 432000 -i | xargs exim -Mrm

Удалить все сообщения, которые реньше, чем Х секунд из очереди (например, 5 дней будет 432 000 секунд)

exiqgrep -y 432000 -i | xargs exim -Mrm

Заморозить все сообщения в очереди от отправителя

exiqgrep -i -f email@example.com | xargs exim -Mf

Удалить все замороженные сообщения из очереди

exipick -zi | xargs exim -Mrm

Удалить все сообщения из очереди (плохая идея)

exiqgrep -i | xargs exim -Mrm
или
exipick -i | xargs exim -Mrm

Поиск в журнальных файлах с помощью exigrep
Утилита exigrep ( не путайте с exiqgrep, использующейся для поиска в очереди ), используется для поиска по лог файлам. Например exigrep может вывести все записи из лог файла с совпадающим ID сообщения, что довольно удобно, учитывая что каждое сообщение занимает 3 строки в лог файле.

Поиск сообщений отправленных с определенного IP адреса:

bash:

exigrep '<= .* [12.34.56.78] ' /path/to/exim_log

Поиск сообщений отправленных на определенный IP адрес:

bash:

exigrep '=> .* [12.34.56.78]' /path/to/exim_log

Данный пример ищет сообщения содержащие символы «=>», и отправленные на адрес «user@domain.tld», далее по конвейеру, результат передается команде grep, которая из полученного результата выбирает строки, содержащие «<=» с информацией об отправителе, почтовом адресе, IP адресе, размере сообщения, ID сообщения и заголовок subject, если логгирование этой строки включено.

bash:

exigrep '=> .*user@domain.tld' /path/to/exim_log | fgrep '<='

Генерировать из лог файла и показать статистику Exim:

bash:

eximstats /path/to/exim_mainlog

То-же что и выше но с более подробными данными:

bash:

eximstats -ne -nr -nt /path/to/exim_mainlog

Аналогично но за определенный день:

bash:

fgrep YYYY-MM-DD /path/to/exim_mainlog | eximstats

В качестве дополнения

Удалить все сообщения в очереди, содержащие в теле, определенную строку:

bash:

grep -lr 'a certain string' /var/spool/exim/input/ |
sed -e 's/^.*/([a-zA-Z0-9-]*)-[DH]$/1/g' | xargs exim -Mrm

Командой выше, мы проверяем содержимое каталога /var/spool/exim/input/, в поисках файлов очереди, содержащих определенную строку в теле сообщения, поскольку команда exiqgrep не умеет просматривать тело сообщений. Если вы решите удалить найденные файлы напрямую, ЭТО БУДЕТ НЕ ПРАВИЛЬНО, используйте предназначенные для этого команды exim.

Если вывод используемой команды слишком длинный, например ID сообщений при exiqgrep -i, которые нужно передать дальше по конвейеру команде exim, может быть превышено количество аргументов командной строки вашей системной оболочки. В этом случае передавайте результат поиска через конвейер, команде xargs, которая будет обрабатывать результаты ограниченными порциями.

Например удалим тысячи сообщений, отправленных с адреса joe@example.com:

bash:

exiqgrep -i -f '' | xargs exim -Mrm
Листы контроля доступа (Access Control List, ACL)
 Exim предоставляет возможность использовать, листы контроля доступа (ACL) на различных этапах SMTP передачи. Условия ACL назначаются в конфигурационном файле exim.conf.
 Начать имеет смысл с HELO.
bash:
# Назначить ACL для использования после команды HELO
acl_smtp_helo = check_helo
# Условия проверки check_helo для ACL:
check_helo:
deny message = Gave HELO/EHLO as «friend»
log_message = HELO/EHLO friend
condition = ${if eq {$sender_helo_name}{friend} {yes}{no}}
deny message = Gave HELO/EHLO as our IP address
log_message = HELO/EHLO our IP address
condition = ${if eq {$sender_helo_name}{$interface_address} {yes}{no}}
accept
!Внимание Используйте проверку HELO на свой страх и риск. Сейчас HELO не имеет такого большого значения в общей схеме SMTP, так что не стоит сильно доверять его содержимому. Не только спамеры используют строку HELO, вы будете удивлены сколько нормальных сообщений может приходить с кривым HELO. Спамерам не составит труда отправлять сообщения с легальной строкой HELO а не писать там «я спамер», так что много спама вы на этом не отсеете.
 Далее, вы можете провести проверку по отправителю или удаленному хосту. В примере показано как фильтровать по содержимому, идущему после команды RCPT TO. Если прием сообщения будет отклонен в этом месте, вы получите больше данных в логах, нежели при блокировке по MAIL FROM.
bash:
# Назначит проверку содержимого после RCPT TO
acl_smtp_rcpt = check_recipient
# Условия для check_recipient ACL
check_recipient:
# [...]
drop hosts = /etc/exim_reject_hosts
drop senders = /etc/exim_reject_senders
# [ Probably a whole lot more... ]
 В приведенном примере для блокировки используются два текстовых файла. В файл /etc/exim_reject_hosts, значения добавляются в виде: имя_хоста/IP_адрес, в файл /etc/exim_reject_senders в виде адреса отправителя, по одной записи в строке.
 Кроме того, можно сканировать содержимое сообщения, на предмет совпадения с регулярным выражением. Имейте в виду, это дает дополнительную нагрузку на процессор, особенно на больших сообщениях.
bash:
# Назначить ACL для использования после команды DATA
acl_smtp_data = check_message
# Условия проверки для check_messages ACL
check_message:
deny message = «Sorry, Charlie: $regex_match_string»
regex = ^Subject:: .*Lower your self-esteem by becoming a sysadmin
accept
Исправление SMTP аутентификации для pine
 В случае, если pine не может использовать аутентификацию на сервере Exim, возвращая сообщение «unable to authenticate», без запроса на ввод пароля, нужно добавить в exim.conf следующие строки.
bash:
begin authenticators
fixed_plain:
driver = plaintext
public_name = PLAIN
server_condition = «${perl{checkuserpass}{$1}{$2}{$3}}»
server_set_id = $2
> server_prompts = :
 Некоторое время назад, данная проблема имела место быть в CPanel, на текущий момент этот недочет исправлен.
Запись в лог файл заголовка Subject
 Один из самых полезных хаков конфигурации Exim. Добавление в exim.conf приведенной строки, позволит писать в лог файл строку subject, писем проходящих через сервер. Это сильно помогает при решении проблем в процессе настройки сервера, а так-же дает дополнительные критерии для отсева спама.
bash:
log_selector = +subject
Отключение identd
 Честно говоря не думаю что протокол identd был когда либо очень полезен. Identd опирается на подключающийся хост, что-бы подтвердить идентификацию ( System UID ), удаленного пользователя, владельца процесса, устанавливающего сетевое соединение. Это может быть в определенной степени полезно в мире системных оболочек и IRC пользователей, но уж никак не на нагруженном почтовом сервере, где пользователем процесса зачастую является просто какой-нибудь «mail», и за этим может быть любой другой MTA. В итоге куча накладных расходов, нулевой результат, лишь задержки identd запросов и как следствие отказы и таймауты.
 Можно запретить Exim делать подобные запросы, установив таймаут 0 секунд в exim.conf.
bash:
rfc1413_query_timeout = 0s
Отключение блокировки вложений
 Что-бы отключить блокировку исполняемых вложений, что CPanel делает по умолчанию, правда не предоставляя при это контроля «для каждого домена», следующий блок нужно добавить в начало файла /etc/antivirus.exim:
bash:
if $header_to: matches «example.com|example2.com»
then
finish
endif
Полезные утилиты Exim
Одним из главных плюсов Exim'а, без сомнения, являются утилиты, которые
поставляются вместе с ним. Они могут значительно упростить рутинные
операции, сократить ваши однострочники раз в 5, и дают возможность
составлять сложные sh-скрипты для некоторых часто повторяемых действий
с очередью и/или логами.

exiqgrep — Выборка из очереди.

Без опций будет идентично exim -bp
Самая главная опция это -h, которая выводит список всех опций.

— f <regexp> — регэксп совпадения с адресом отправителя
— r <regexp> — регэксп совпадения с адресом получателя
— s <regexp> — регэксп совпадения с полем размера (именно с полем
размера, в том виде как оно указывается при выводе exim -bp)
регэкспы не надо заключать в //
— y <seconds> — выводит сообщения «младше» заданного количества секунд
— o <seconds> — выводит сообщения «старше» заданного количества секунд
— z — только frozen сообщения
— x — все кроме frozen
— c — Показать только количество совпадений (в зависимости от версии
показывает либо просто число, либо фразу типа «15 matches out of 78
messages»
— l — Показывает полную информацию, как её выводит exim (включено по умолчанию)
— i — Показывает только IDs совпавших сообщений
— b — Показывает совпадения в «кратком» формате. Одна строка: ID, From и To
— R — Выводит сообщения в обратном порядке

Разумеется, опции можно комбинировать и делать вещи типа:

exiqgrep -zif '^<>$'

что выводит нам ID замороженных баунсов...

На основе этого можно написать такой вот скрипт

#!/bin/sh
if ! [ `which exim 2>/dev/null` ]; then
echo «Sorry, exim binary not found! Exit now.»
exit
fi
if ! [ `which exiqgrep 2>/dev/null` ]; then
echo «Sorry, exiqgrep binary not found! Exit now.»
exit
fi
if [ "$1" == "cf" ]; then
num_of_frz_mes=`sudo exiqgrep -zif '^<>$|wc -l`
sudo exiqgrep -zif '^<>$'|xargs sudo exim -Mrm > /dev/null
echo «$num_of_frz_mes frozen bounces deleted»
exit
fi
if [ "$1" == "c" ]; then
num_of_mes=`sudo exiqgrep -if '^<>$'|wc -l`
sudo exiqgrep -if '^<>$'|xargs sudo exim -Mrm > /dev/null
echo «$num_of_mes bounces deleted»
exit
fi
num_of_mes=`sudo exiqgrep -if '^<>$'|wc -l`
num_of_frz_mes=`sudo exiqgrep -zif '^<>$'|wc -l`
echo «$num_of_mes bounces currently in the queue»
echo «$num_of_frz_mes frozen bounces currently in the queue»

Запуск без опций показывает количество баунсов в очереди.

с — удалить все баунсы (не надо так делать!)
cf — удалить все frozen баунсы

А можно ускорить доставку для определённого домена (-v можно убрать,
разумеется):

exiqgrep -i -r 'domain.com$' | xargs exim -v -M

Иногда, при использовании exiqgrep появляется такое

Line mismatch: 236d 1HOnvz-00069X-8w <info@lischer.com.>

Лечится так

exim -bpr | grep «^[0-9][0-9][0-9]d» | awk `{print $2}' | xargs exim -Mrm

Я не буду рассасывать, что это значит и как такое получается потому,
что это «выходит за рамки статьи».

exipick
-------

exipick — показывает сообщения из очереди по разным критериям и в разных форматах

Создана как замена exiqgrep'у. Лично мне хватает последнего, но если
захочется чего-нибудь помощнее читайте exipick --help или perldoc exipick

exiqsumm — Анализ очереди

Сама по себе эта утилита ничего не делает. На вход ей обязательно надо
подать очередь exim'а.

exim -bp | exiqsumm

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

По умолчанию вывод сортируется по доменам в алфавитном порядке. Есть и
другие опции
— a — сортирует по возрасту самого старого сообщения
— c — сортирует по количеству сообщений
— b — показывает баунсы отдельно, строчки помечаются (b). Т.е. для тех
доменов где есть баунсы будет две строки, одна с b, другая без нее.
— f — показывает «замороженные» сообщения
— s — показывает и домен с которого отправлено и письмо, и домен
получатель. Соответсвенно каждая «пара» считается отдельно.

А вот так можно выявлять спамеров.

exim -bp | exiqsumm -c -s | head

В выводе появится что-то типа

root@domain.ru [~]# exim -bp | exiqsumm -c -s | head
Count Volume Oldest Newest Domain
----- ------ ------ ------ ------
668 814KB 74m 66m server.ru > yahoo.com
653 788KB 3h 66m server.ru > mail.ru
68 82KB 66m 66m server.ru > list.ru

Разумеется вместо server.ru будет qualify domain (подробнее см. опцию
— f коммандной строки), или домен отправителя если шлют через SMTP.

Узнаем, что это за негодяй

exiqgrep -b -f 'server.ru' -r 'mail.ru' | awk '{print $3}' | sort | uniq -c | sort -n | tail

Самый нижний он и есть.

Хотя все это можно сделать проще и за один заход, с помощью exiqgrep

exiqgrep -b | awk '{print $3}' | sort | uniq -c | sort -n | tail

Ну и соответственно удалить всю очередь от него

exiqgrep -i -f '<spamer@server.ru.>' | xargs exim -Mrm

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

MID=`exiqgrep -i -f '<spamer@server.ru.>'|tail -1`;exim -Mvl $MID; exim -Mvh $MID

Но вернемся к exiqsumm. У этой утилиты есть пара важных нюансов.
Во-первых, считает она не сами сообщения а «доставки». И если некоторые
сообщения имеют более одного получателя, то доставок будет больше чем
сообщений. Во-вторых, домены на которые доставляется письмо в
результате альясинга или форвардинга — не включаются (если не
использовалась опция «one_time» роутера «redirect» для конвертации из в
адреса «верхнего уровня»). Поэтому всегда надо смотреть логи.

exigrep — Выборка из логов

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

Использование

exigrep [-I] [-l] [-t ] [-v] []...

— I — включает регистрозависимость
— l — отключает обработку регулярных выражений в паттерне (все символы
начинают обрабатываться «как есть»)
— t<n> — в качестве n нужно указывать количество секунд. Выводятся
только сообщения, которые провели в очереди больше чем n секунд.
— v — опция идентична grep'овской. Выводит только строки не содержащие
паттерн (вернее, строки относящиеся к сообщениям у которых ни в одной
строке нет паттерна).

Логи можно подавать на стандартный ввод или через пробел после всех
опций. Логи могут быть в архиве (вообще говоря, все это дело
определяется опциями сборки ZCAT_COMMAND и COMPRESS_SUFFIX в файле
Local/Makefile).

eximstats — Статистика на базе логов

Утилита парсит логи экзима (или syslog'а) и выводит статистический
анализ по всем содержащимся сообщениям.
Вывод может быть в трех форматах: txt, html, xls (Excel).

Использование

eximstats [Output] [Options] mainlog1 mainlog2

По умолчанию скрипт выведет статистику в STDOUT в формате txt. Например
можно сделать так

eximstats mainlog1 mainlog2 ... > report.txt

но лучше так

eximstats -txt=report.txt mainlog1 mainlog2

Вместо txt можно указать html или xls, чтобы вывод был в
соответствующем формате.

Уже готовые отчеты можно объединить в один.

eximstats -merge -html [Options] report.1.html ... > weekly_rep.html

У программы масса опций, посмотреть их можно так

eximstats -help

или так

perldoc eximstats

Если отчеты в html, то можно даже png-графики выводить.
Описывать, что получается в отчете, смысла, думаю, нет. Стоит просто
попробовать и посмотреть. Статистика очень мощная, если есть проблемы,
они винды сразу.

exim_checkaccess — проверка приема для адреса с IP

Очень простая программа для проверки Relay. Заменяет «exim -bh».
Используем так:

exim_checkaccess <IP address> <email address> [exim options]

IP — IP отправителя
email address — адрес который будет указываться в RCPT TO
Обе опции обязательные (к сожалению, я не нашел как проверить «с любого
IP»). После опций можно добавить любые опции экзима. Т.к. утилита
использует <> в качестве отправителя удобно использовать её так:
exim_checkaccess 10.9.8.7 A.User@a.domain.example -f
himself@there.example

Это не все утилиты, которые идут с exim'ом. Описал только те, которые
считаю наиболее полезными.

Остальные утилиты просто перечислю:

* exiwhat — список того, что делают процессы exim`a
* exicyclog — ротация лог-файлов
* exim_dbmbuild — сборка файла DBM
* exinext — извлечение информации повторов
* exim_dumpdb — дамп БД подсказок
* exim_tidydb — очистка БД подсказок
* exim_fixdb — правка БД подсказок
* exim_lock — блокировка файла почтового ящика (mailbox)
* eximon — показывает в X'ах информацию о состоянии очереди exim'a, и о том, что exim делает

Есть сторонние утилиты, например, exilog — обеспечивает визуализацию
логов от многих серверов exim'a.
Lire — аналог eximstats, но на самом деле это более глобальная
программа которая анализирует логи многих программ и выводит

статистику.

Ссылки
Заметка написана на основе официальной документации к Exim. В процессе
написания использовались некоторые формулировки из перевода документации
отсюда.

Официальный сайт программы
Официальная Wiki Exim'а
Сайт VirtualExim
Сайт утилиты exilog
[urlspan]сайт Lire[/urlspan]
FAQ по Exim MTA
Диспут на тему Exim vs Postfix
Virtual Domains with Exim + Courier-IMAP + MySQL
Установка почтового сервера на базе Exim

Ставим nginx
deathstar# cd /usr/ports/www/nginx
deathstar# make install clean

в /etc/rc.conf добавляем:
nginx_enable="YES"

Ставим MySQL
deathstar# cd /usr/ports/databases/mysql51-server
deathstar# make install clean

в /etc/rc.conf добавляем:
mysql_enable="YES"
Запускаем MySQL

deathstar# /usr/local/etc/rc.d/mysql-server start

Задаем пароль для root в MySQL ( в скобках сам пароль )
deathstar# mysqladmin -u root password 'password'

Ставим PHP ( отмечаем [*] FPM Build FPM version )
deathstar# cd /usr/ports/lang/php5
deathstar# make install clean

в /etc/rc.conf добавляем:
php_fpm_enable="YES"

Приводим файл /usr/local/etc/php-fpm.conf к такмоу виду:

[global]
pid = run/php-fpm.pid
error_log = /var/log/php-fpm.log
events.mechanism = kqueue
include=/usr/local/etc/php-fpm.d/*.conf

Создаем каталог,в котором будут лежать описания пулов для PHP-FPM ( кому то может пригодиться, если юзеров для сайтов больше чем один ):

deathstar# mkdir -p /usr/local/etc/php-fpm.d/ и описываем пул
deathstar# ee /usr/local/etc/php-fpm.d/www.conf

[www]
user = www
group = www
listen = /tmp/php-fpm.sock
listen.backlog = -1
pm = dynamic
pm.max_children = 2
pm.start_servers = 1
pm.min_spare_servers = 1
pm.max_spare_servers = 2
pm.max_requests = 500
php_admin_value[error_log] = /var/log/fpm-php.www.log
php_admin_value[memory_limit] = 128M

Запускаем PHP-FPM:
deathstar# /usr/local/etc/php-fpm start

Ставим Vexim (отмечаем MySQL):
deathstar# cd /usr/ports/mail/vexim/
deathstar# make install clean

Ставим модуль p5-DBD-mysql51
deathstar# cd /usr/ports/databases/p5-DBD-mysql51/
deathstar# make
deathstar# make install clean

Запускаем скрипт:
perl /usr/local/share/vexim/create_db.pl --act=newdb --dbtype=mysql -uid=110 --gid=110 --mailstore=/usr/local/mail
deathstar#
Please enter the username of the mysql superuser: root
Please enter the password of the mysql superuser:
Please enter the name of your NEW database: vexim
--------------------------------------------------
Database: vexim will be created
--------------------------------------------------
Is this correct? (Y = continue / anykey = exit ): Y

Please enter a password for the 'vexim' database user:
Confirm password:
Please enter a password for the 'siteadmin' user:
Confirm password:
The user 'siteadmin' has been added with the password
Database created successfully!

Создаем каталог с виртуальными хостами для nginx

deathstar# mkdir -p /usr/local/etc/nginx/vhosts

Приводим /usr/local/etc/nginx/nginx.conf к такому виду:

worker_processes 2;

events {
use kqueue;
worker_connections 2048;
}

http {
include mime.types;
default_type application/octet-stream;
sendfile on;
client_body_buffer_size 16K;
client_header_buffer_size 1k;
client_max_body_size 32M;
large_client_header_buffers 2 1k;
client_body_timeout 10;
client_header_timeout 10;
keepalive_timeout 5 5;
send_timeout 10;
reset_timedout_connection on;
server_tokens off;
gzip on;

# Закрываем обращения по IP адресу
server {
listen 80 default_server;
server_name _;
return 444;
}

# PHP-FPM
upstream php-fpm {
server unix:/tmp/php-fpm.sock;
}

# Инклюдим файлы с виртуальными хостами
include /usr/local/etc/nginx/vhosts/*;
}

Делаем виртуальный хост в nginx для Vexim

deathstar# ee /usr/local/etc/nginx/vhosts/exim.deathstar.name

server
{
listen 80;
server_name exim.deathstar.name;
access_log /var/log/nginx/exim-access.log;
error_log /var/log/nginx/exim-error.log;
root /usr/local/www/vexim;
index index.php;
charset utf-8;

location ~ .php$
{
fastcgi_pass php-fpm;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include /usr/local/etc/nginx/fastcgi_params;
}

location ~ /.ht
{
deny all;
}
}

Редактируем конфиг Vexim
deathstar# ee /usr/local/www/vexim/config/variables.php";
и вводим данные для подключения к базе данных введенные ранее.
Создаем группу и пользователя exim:
deathstar# pw groupadd vexim -g 90
deathstar# pw useradd vexim -u 90 -g vexim -d /usr/local/mail -m -s /nonexistant

Устанавливаем Exim ( отмечаем опцию SA-EXIM для работы SpamAssasin) :
deathstar# cd /usr/ports/mail/exim && make install clean
Добавляем в /etc/rc.conf:
exim_enable="YES"

Копируем и правим конфиги
deathstar# cd /usr/local/etc/exim/
deathstar# cp /usr/local/share/doc/vexim/docs/*.conf ./
deathstar# cp /usr/local/share/doc/vexim/docs/configure ./
deathstar# ee /usr/local/etc/exim/configure

Находим строку:
MY_IP = CHANGEописываем свой ip
MY_IP = 46.38.63.5/code>
Находим:
trusted_users = avleen:www
и удаляем avleen .Остается:

trusted_users = www
exim_user = mailnull
exim_group = mail
never_users = root

Находим закоментированную строку, отвечающую за подключение к MySQL серверу,раскоментируем ее и поставим там свой пароль:
hide mysql_servers = localhost::(/tmp/mysql.sock)/vexim/vexim/vexim
Раскоментируем:
AINS = SELECT DISTINCT domain FROM domains WHERE type = 'relay' AND domain = '${quote_mysql:$domain}'
ALIAS_DOMAINS = SELECT DISTINCT alias FROM domainalias WHERE alias = '${quote_mysql:$domain}'timeout_frozen_after = 2d
log_selector = +subject

Изменяем путь к антивируму ClamAV:
Находим:
av_scanner = clamd:/var/run/clamav/clamd и меняем на av_scanner = clamd:/var/run/clamav/clamd.sock

Добавляем в /etc/rc.conf
spamd_enable="YES" и запускаем
exim# /usr/local/etc/rc.d/sa-spamd start

Ставим ClamAV:
deathstar# cd /usr/ports/security/clamav && make install clean
Добавляем в /etc/rc.conf:
clamav_freshclam_enable="YES"
clamav_clamd_enable="YES"

и запускаем
deathstar# /usr/local/etc/rc.d/clamav-clamd start
Запускаем обновление баз ClamAV
deathstar# /usr/local/etc/rc.d/clamav-freshclam start

Добавялем в /etc/rc.conf
exim_enable="YES"

Устанавливаем Dovecot:
deathstar# cd /usr/ports/mail/dovecot && make install clean
Настройки хранятся в файле /usr/local/etc/dovecot.conf
Приводим конфиг к такому виду

base_dir = /var/run/dovecot/
protocols = imap pop3 imaps pop3s
protocol imap {
listen=*:143
}
protocol pop3 {
listen=*:110
}
disable_plaintext_auth = no
log_path =/var/log/dovecot
log_timestamp = "%b %d %H:%M:%S "
syslog_facility = mail
ssl = no
ssl_parameters_regenerate = 0
mail_location = maildir:~/Maildir
mail_privileged_group = mail
mail_debug = yes
mail_log_prefix = "%Us(%u): "
dotlock_use_excl = yes
verbose_proctitle = yes
first_valid_uid = 90
first_valid_gid = 90
maildir_copy_with_hardlinks = yes
protocol imap {
mail_executable = /usr/local/libexec/dovecot/imap
imap_client_workarounds = delay-newmail netscape-eoh tb-extra-mailbox-sep
}

protocol pop3 {
mail_executable = /usr/local/libexec/dovecot/pop3
pop3_uidl_format = %08Xu%08Xv
pop3_client_workarounds = outlook-no-nuls oe-ns-eoh
}
protocol lda {
postmaster_address = postmaster@example.com
sendmail_path = /usr/sbin/sendmail
}
auth_username_format = %Lu
auth_verbose = yes
auth_debug = yes
auth default {
ssl_require_client_cert=no
ssl_username_from_cert=no
mechanisms = plain login
passdb pam {
args = session=yes dovecot
}
passdb sql {
args = /usr/local/etc/dovecot-sql.conf
}
userdb passwd {
args = blocking=yes
}
userdb sql {
args = /usr/local/etc/dovecot-sql.conf
}
user = root
socket listen {
master {
path = /var/run/dovecot/auth-master
mode = 0600
}
client {
path = /var/run/dovecot/auth-client
mode = 0660
}
}
}
dict {
}
plugin {
}

Настраиваем подключение к MySQL в файле dovecot-sql.conf

deathstar# ee /usr/local/etc/dovecot-sql.conf

driver = mysql
connect = host=/tmp/mysql.sock user=vexim password=PASSWORD dbname=vexim
default_pass_scheme = MD5-CRYPT
password_query = SELECT crypt as `password` FROM users,domains WHERE users.username = '%u' AND users.enabled = '1' AND users.type = 'local' and domains.enabled = '1' and domains.domain_id = users.domain_id
user_query = SELECT pop as home, uid, gid FROM users WHERE username = '%u'

Добавляем запись в /etc/rc.conf:
dovecot_enable="YES"
Запускаем Dovecot:

deathstar# /usr/local/etc/rc.d/dovecot start

Ставим RoundCube (выбираем MySQL):

#deathstar cd /usr/ports/mail/roundcube/
deathstar# make install clean

И далее команды по порядку:

deathstar#cd /usr/local/www/roundcube
deathstar# chmod 777 logs/
deathstar# chmod 777 temp/

Создаем базу

deathstar# mysql -p
Enter password:
Welcome to the MySQL monitor. Commands end with ; or g.
mysql> CREATE DATABASE roundcubemail DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;
Query OK, 1 row affected (0.01 sec)

mysql> GRANT ALL PRIVILEGES ON roundcubemail.* TO roundcube@localhost IDENTIFIED BY 'password';
Query OK, 0 rows affected (0.00 sec)

mysql> quit
Bye

</code>
<code>deathstar# cd /usr/local/www/roundcube/
deathstar# mysql -p roundcubemail < SQL/mysql.initial.sql

deathstar# cp config/db.inc.php.dist config/db.inc.php
deathstar# ee config/db.inc.php

Правим конфигурационный файл /usr/local/www/roundcube/config/db.inc.php,
отвечающий за соединение с базой данных:
$rcmail_config['db_dsnw'] = 'mysql://roundcube:pass@localhost/roundcubemail';

Правим файл main.inc.php, содержащий основные настройки:
deathstar# ee config/main.inc.php

$rcmail_config['default_host'] = 'localhost'; #хост, на котором находится почта
$rcmail_config['username_domain'] = ' mydomain.ru'; #домен, который будет автоматически добавляться к имени пользователя
$rcmail_config['mail_domain'] = 'mydomain.ru'; #почтовый домен
$rcmail_config['default_port'] = 143; #порт imap
$rcmail_config['imap_auth_type'] = null; #тип авторизации imap
$rcmail_config['smtp_server'] = 'localhost'; #сервер smtp
$rcmail_config['smtp_user'] = '%u';
$rcmail_config['smtp_pass'] = '%p';
$rcmail_config['smtp_auth_type'] = 'CRAM-MD5'; #тип авторизации smtp
$rcmail_config['create_default_folders'] = TRUE; #при первом логине юзера создаются дефолтные почтовые папки (Входящие, Исходящие, Корзина и тд.)
$rcmail_config['language'] = ru_RU; #локализация

И добавляем виртуальный хост в nginx для Roundcube

deathstar# ee /usr/local/etc/nginx/vhosts/mail.deathstar.name

server
{
listen 80;
server_name mail.deathstar.name;
access_log /var/log/nginx/mail-access.log;
error_log /var/log/nginx/mail-error.log;
root /usr/local/www/roundcube;
index index.php;
charset utf-8;

location ~ .php$
{
fastcgi_pass php-fpm;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include /usr/local/etc/nginx/fastcgi_params;
}

location ~ /.ht
{
deny all;
}
}

Перезапускаем PHP-FPM и NGINX

deathstar# /usr/local/etc/rc.d/nginx restart && usr/local/etc/rc.d/php-fpm restart

Теперь Roundcube доступен по адресу http://mail.deathstar.name а Vexim по http://exim.deathstar.name

Заходим по адресу http://exim.deathstar.name
Логинимся под siteadmin и пароль, что выставляли ранее
Жмем Add local domain
Прописываем домен, имя администратора ( по умолчанию postmaster, можно сменить на любое , так же создастся ящик вида postmaster@domain, а создадим например admin )
прописываем пароль ( например pass )
повторяем пароль
отмечаем антиспам и антивирус ( по желанию ) и жмем Submit

У нас появился почтовый аккаунт admin@domain с паролем pass

Чтоб для созданного домена создать еще ящик, логинимся под логином админа домена, в нашем случае – admin

Жмем Add, delete and manage POP/IMAP accounts
Потом Add User
Прописываем имя ( любое, оно просто для отображения в списке юзеров )
логин ( например user )
два раза пароль ( например userpass )
Has domain admin privileges? – отмечаем, есди хотим сделать юзера тоже админом домена
И жмем Submit.
У нас появился почтовый аккаунт user@domain с паролем userpass

Теперь можно зайти в roundcube по ссылке http://mail.deathstar.name под логином user@domain и паролем userpass