Ключевые слова:mail, spam, filter, (найти похожие документы)
From: jdspb <jd@mail.ru.>
Newsgroups: openforum
Date: Mon, 19 Jul 2005 14:31:37 +0000 (UTC)
Subject: Алгоритм для фильтрации спама
Оригинал: http://www.opennet.dev/openforum/vsluhforumID11/11.html#24
Месяц назад я попробовал новый почтовик XMail v 1.21 /все в одном
флаконе, smtp, pop3, imap и т.д. http://www.xmailserver.com/ .
Заработало через 5 мин. после подстройки конфига, все достаточно
ясно и прозрачно. Для машины выделил несколько доменов, на которые
из-за особенностей их владельцев сыпалось довольно много спама
/точнее - только спам/.
Основной сервер работает с MTA sendmail и его пока трогать боязно,
т.к. об XMail практически нет никаких отзывов, а которые есть,
часто путают с одноименной программой под X11-unix. Так вот - спам
полился широкой речкой...
Идеи, которые заложены в статье http://linux.ufaras.ru/regex.html
были реализованы уже давно, помогали конечно, но недостаточно.
В xmail есть возможность обрабатывать письма на стадии
соединения - делается это просто: название фильтра включается в
файл filters.pre-data.tab, в котором указывается внешняя программа
обработчик.
Короче, взяв в руки логи, за пару дней написал собственный
фильтр-обработчик писем. За основу был взят тезис, что нормальный
почтовый сервер должен иметь нормальные атрибуты.
а теперь bash и регекспы...конспективно
Фильтру на вход передаются два параметра File=$1 и RemoteAddress=$2
1. Отсекаем локальные адреса
if [ "$RemoteAddress" == "127.0.0.1" ]; then exit; fi
2. Whitelist - список своих левых адресов /правые и так проходят
нормально :-) /
Found=`cat /var/XMailRoot/filters/whitelist.ip|
grep $RemoteAddress|wc -l|sed -e 's/ //g'`
3. Определяем обратную запись
Relay=`dig -x $RemoteAddress | grep PTR |grep in-addr.arpa.|
awk '{print $5}'`
--- a теперь начинаем резать ---
4. Считаем минусы в имени: 2-допустимо, больше - режем...
Minuses=`echo "$Relay" | sed -e 's/[a-z A-Z 0-9 .]*//g' | wc -m|
sed -e 's/ //g'`
5. Считаем группы цифр: режем, ежели больше трех...
DigGroups=`echo "$Relay" | sed -e 's/[0-9]\{2,\}/+/g'
-e 's/[a-z A-Z]//g' -e 's/-//g' -e 's/\.//g' -e 's/[0-9]//g' |
wc -m|sed -e 's/ //g
6. Скурпулезно считаем точки: у порядочного сервера больше трех не
бывает.../или я не прав?/
Dots=`echo "$Relay" | sed -e 's/[0-9 a-z A-Z -]//g' | wc -m|sed -e 's/ //g'`
7. И последнее, проверяем на "неприличные" слова из списка
BadWords="dsl. dslam. dial cable. ppp dhcp pool node dyn- host-
host. home. dynamic try user client customer \-gw. modem dynip bbtec"
Заработало практически сразу, я даже числа знаков и точек не
подбирал.
Спам конечно проходит, но это уже единицы, и их можно обработать
руками.
Итог работы: за 15 дней июля на сервер пришло 5557 запросов на
доставку /100%/
Из них, отвергнуто без обработки 2799 /50%/ по списку
"spammers.tab", составленному по логам работы этого фильтра - это
так называемый рецидив;
1008 /18%/ писем сервер отверг по внешним спамерским спискам.
Статистика такова: из 17 прописанных серверов реально работают
только пять
list.dsbl.org 727
bl.spamcop.net 249
sbl.spamhaus.org 25
dul.ru 6
relays.ordb.org 1
1346 /24%/ писем сервер отверг благодаря работе фильтра. Это т.н.
новые спам-письма Из них:
566 - не прописан ДНС;
442 - слишком много минусов;
241 - много точек;
73 - группы чисел;
24 - из списка слов.
пример из лога для каждого случая:
2005-07-11 03:26:27 58.19.43.13 No DNS entry
2005-07-11 03:26:27 201.2.154.46 Minuses=3
201-002-154-046.osrce204.dial.brasiltelecom.net.br
2005-07-11 03:35:27 195.5.144.26 Dots =3
ppp-144-26.dialup.metrocom.ru
2005-07-11 04:03:47 200.124.28.78 DigGroups=7
cm-200.124.28.78.cableonda.net.28.124.200.in-addr.arpa.
2005-07-04 10:30:31 195.98.67.39 Bad
Word uas1-pool-39.vrn.ru.
Через фильтры просочилось 404 письма, из них 15х24=360 - это
служебные, ежечасно отправляемые с самого сервера отчеты.
Выводы: система фильтрации "пропустила"
100%*(404-15*24)/(5557-15*24)=0,85% спам-писем, о чем честно
сделала записи в логах, типа
2005-07-13 10:45:02 195.208.235.29 Pass thru... relay02.infobox.ru.
Мне кажется, что данный алгоритм можно использовать и для других
MTA.
Определение обратной записи предлагаю заменить на
Relay='dig -x $RemoteAddress +noquestion +noauthority +noadditional +nocomments +nostats +nocmd | grep PTR -m 1 | awk '{print $5}''
Это избавит от двух ошибок:
1) для одного ip несколько PTR
2) когда PTR является алиасом на запись не содержащую in-addr.arpa.