Страница 1 из 2

Exim-требуется помощь по отсеканию спама

Добавлено: 2006-12-25 12:06:31
DeVeO
Добрый день. Exim поставлен по статье Лиссяры-все прекрасно работает (огромный респект Лиссяре). Но начал валиться спам-20 секундные задержки не помогают. Возникла идея-проверять существование сервера от которого идет отправка. Вроде бы вычитал, что в Exim'e есть опция callback. Может кто-нибудь посоветовать как это сделать?

Добавлено: 2006-12-25 12:10:10
Alex Keda
значит пора ставить чё-то посерьёзней
=========
щас это неактульно. Спамеры стали брать сервера мощщнее и вполне ждут и по минуте...

Добавлено: 2006-12-25 12:15:20
DeVeO
Посерьезней- в каком смысле? Spamd, Spamassasin...,

Добавлено: 2006-12-25 12:17:35
dikens3
1. Включить SPF

Код: Выделить всё

# Проверка SPF
  deny    message       = "[SPF] $sender_host_address is not allowed to send mail from $sender_address_domain"
          log_message   = SPF check failed
          spf           = fail
          hosts         = !+relay_from_hosts  : !+my_lan_hosts : *
2. Проверить отправителя.

Код: Выделить всё

# Прибиваем всякие dialup и т.п.
  deny    message       = "SPAM!!! If you think that system is mistaken, please report details to postmaster@domain.ru"
          condition     = ${if match{$sender_host_name}{client|node|ppp|cable|dialup|pool|peer|dhcp|dslam}{yes}{no}}

Код: Выделить всё

# Проверяем, существует ли домен отправителя
  deny    log_message   = Sender verify failed
         !verify        = sender/callout=5s,maxwait=30s
P.S. в spf может ещё и softfail добавить.

Добавлено: 2006-12-25 12:30:07
DeVeO
Спасибо. Попробую. Я так понял, что перечисленное можно вставить в секцию acl_check_rcpt: А my_lan_hosts заменить на внутреннюю сеть 192.168.0.0/24 Правильно?

Добавлено: 2006-12-25 12:54:57
dikens3
Ага.
Я в основном конфиге так сделал:

Код: Выделить всё

hostlist         my_lan_hosts = 192.168.x.x/24

Добавлено: 2006-12-25 13:08:20
DeVeO
Понял. Спасибо. Ну и как у тебя эффективность этих правил?

Добавлено: 2006-12-25 13:40:52
dikens3
Я на exim ещё не переехал. :-(
Я готовил SMTP аналогичный тому, что у меня в работе. Статистики нет. :-(

Добавлено: 2006-12-25 13:47:46
DeVeO
Понятно. А ты не мог бы пояснить как работает правило с SPF (в Exim'e)? Не очень понимаю... :oops:

Добавлено: 2006-12-25 14:27:04
dikens3
DeVeO писал(а):Понятно. А ты не мог бы пояснить как работает правило с SPF (в Exim'e)? Не очень понимаю... :oops:
Мог. :-)

Тут на форуме уже было обсуждение SPF
Почтовые серваки регистрируются в DNS с указанием IP-Адресов, которым разрешена отправка почты от их домена.

т.е. mail.ru

Код: Выделить всё

ns# nslookup -type=txt mail.ru
mail.ru text = "v=spf1 ip4:194.67.57.0/24 ip4:194.67.23.0/24 ip4:194.67.45.0/24 ~all"

ns# nslookup -type=txt inbox.ru
inbox.ru        text = "v=spf1 ip4:194.67.57.0/24 ip4:194.67.23.0/24 ip4:194.67.45.0/24 ~all"
От имени @mail.ru и @inbox.ru разрешено посылать подсетям описанным выше.
all означает что это все диапазоны адресов с которых можно посылать от вышеперечисленных доменов.
~all - тильда перед all означает что действие остаётся на усмотрение пользователя. В данном случает проверка SPF вернёт значение softfail. (В списке допустимых такого IP нет, но реакцию на это выбираешь ты. Можно прибавлять количество баллов к примеру в спам фильтрах, а не сразу убивать)
Если mail.ru сделает -all, тогда fail

Добавлено: 2006-12-25 14:32:10
DeVeO
Спасибо огромное...

Добавлено: 2006-12-25 16:44:45
Alex Keda
во как... чё-то я тему про SPF пропустил....

Добавлено: 2006-12-25 17:01:45
Alex Keda

Код: Выделить всё

2006-12-25 17:00:08 Exim configuration error in line 416 of /usr/local/etc/exim/configure:
  error in ACL: unknown ACL condition/modifier in "spf           = fail"
облом. надо маны курить. :)

Добавлено: 2006-12-25 18:04:14
dikens3
Пересобрать с поддержкой SPF

Добавлено: 2006-12-25 19:31:18
Alex Keda
да догадался уже :))

Добавлено: 2006-12-28 16:25:11
Maks
Хватает всего того, что ниже.
Работает на сервере для 4-х доменов. Пропускает спама в общей сложности 2-3%

Код: Выделить всё


# ACL for entire mail
begin acl

# This rules are work for all
acl_check_rcpt:

  # Allow mail from localhost not for TCP/IP
  accept  hosts = :

  # Check for incorrect symbols in address @; %; !; /; |.
  # If `percent_hack_domains` enabled than % should be removed
  # Check local domains
  deny    message       = "Incorrect symbol in address"
          domains       = +local_domains
          local_parts   = ^[.] : ^.*[@%!/|]

  # Check not local domains
  deny    message       = "Incorrect symbol in address"
          domains       = !+local_domains
          local_parts   = ^[./|] : ^.*[@%!] : ^.*/\\.\\./

  # Accept mail for local-domain postmasters
  accept  local_parts   = postmaster
          domains       = +local_domains

  # Sender address verification
  #require verify        = sender

  # Deny all without HELO/EHLO
  deny    message       = "Where your HELO/EHLO?! Gona read RFC..."
          condition     = ${if eq{$sender_helo_name}{}{yes}{no}}

  # Allow all from auth users
  accept  authenticated = *

# Deny from all who send IP in HELO
  deny    message       = "Your IP in HELO??? Hmm... I think you're spammer!"
          hosts         =  * : !+relay_from_hosts : !192.168.0.0/24
          condition     = ${if eq{$sender_helo_name}\
    {$sender_host_address}{true}{false}}

# Deny from all who send our IP in HELO
  deny    condition     = ${if eq{$sender_helo_name}\
    {$interface_address}{yes}{no}}
          hosts         = !127.0.0.1 : !localhost : *
          message       = "My IP in YOUR HELO??? Hmm... I think you're spammer!"

# Deny from all who send my hostname in HELO
  deny    condition     = ${if eq{$sender_helo_name}{$primary_hostname}{yes}{no}}
          hosts         = !127.0.0.1 : !localhost : *
          message       = "My hostname in YOUR HELO??? Hmm... I think you're spammer!"

# Deny from all who send just numeric HELO
   deny    condition     = ${if match{$sender_helo_name}\
     {\N^\d+$\N}{yes}{no}}
           hosts         = !127.0.0.1 : !localhost : *
           message       = "Your HELO containts only number! Gona read RFC..."

# Deny from all who didn't send sender address
#   deny    condition     = ${if eq{$sender_address}{}{yes}{no}}
#           hosts         = !127.0.0.1 : !localhost : *
#           message       = "Where sender of this mail?! Gona read RFC..."

"# Deny from all who didn't send sender address" - это место, как было в примере Лисы, я закоментил, потому что начинаются проблемы, когда кто-то где то шлет письма на адреса для моего сервера, и принимающий сервер для отправки пытается коннектиться к моему для проверки адресата. Проверяет он его обычно просто отправляя RCPT TO: без MAIL FROM: и его сразу обрубает (кто знает, как полечить, кроме как каментить, подскажите, пожалуйста...)

Код: Выделить всё

# Deny from all who didn't send sender address (Space)
   deny    condition     = ${if match{$sender_address}{\N^\s+$\N}{yes}{no}}
           hosts         = !127.0.0.1 : !localhost : *
           message       = "Where _RIGHT_ sender of this mail?! Gona read RFC..."

  # Deny all from adsl, pppoe, etc...
  deny    message       = "Your hostname is very bad to send email (adsl, poll, ppp & etc). You should use provider's SMTP server."
          condition     = ${if match{$sender_host_name} \
                               {adsl|dialup|dial-up|pool|peer|dhcp|pppoe|dynamic} \
                               {yes}{no}}

  # DELAY
  warn
        # Default delay
        set acl_m0 = 20s
  warn
        # For friendly hosts delay 0s
        hosts = +relay_from_hosts:my_own_friendly_servers_net/24
        set acl_m0 = 0s
  warn
        # Delay logging
        logwrite = Delay $acl_m0 for $sender_host_name \
[$sender_host_address] with HELO=$sender_helo_name. Mail \
from $sender_address to $local_part@$domain.
        delay = $acl_m0

  # Check recipient in local domains
  # If not match go to other ACL
  accept  domains       = +local_domains
          endpass
          message       = "In my mailserver not stored this user"
          verify        = recipient

  # Check recipient in relayed domains
  # If not match go to other ACL
  accept  domains       = +relay_to_domains
          endpass
          message       = "Mail server not know how relay to this address"
          verify        = recipient

  # Use public blacklist's databases
  deny    message       = "Your IP in blacklist. See $dnslist_domain \n $dnslist_text"
          dnslists      = relays.ordb.org : \
                          opm.blitzed.org : \
                          cbl.abuseat.org : \
                          bl.csma.biz : \
                          dynablock.njabl.org : \
                          relays.ordb.org

  # Allow mail from relay_from_hosts list
  accept  hosts         = +relay_from_hosts

  # !!!ALL OTHER DENY!!!
  deny    message       = "Hey, man! I think you're spammer... So, no any mail from your! Bye!"



# ACL for mail body

acl_check_data:

# Deny China messages
  deny message = "Hm... China Spam??? Gona Hell!"
  condition = ${if match{$message_body} \
              {105[-_]*51[-_]*86|778[-_]*98[-_]*94} \
              {yes}{no}}

  # Check mail for viruses
  deny malware = *
  message = "In e-mail found VIRUS - $malware_name"

  # Other allow
  accept


Кроме всего прочего убрана задержка (Delay) для тех хостов, которым доверяем (my_own_friendly_servers_net/24).

Добавлено: 2006-12-28 16:35:42
Alex Keda
Щас для телекомовской мыльницы конфиг пишу. Доделаю - выложу.
Очень много интересных идей, явялющихся продолжением старых....

Добавлено: 2006-12-28 19:22:18
grave
lissyara писал(а):Щас для телекомовской мыльницы конфиг пишу. Доделаю - выложу.
Очень много интересных идей, явялющихся продолжением старых....
любопытно.. ждем-с..

Добавлено: 2007-01-06 21:21:02
robi
не слал заморачиваться с SPF
прикрутил greylist
режет 99% спама
прикручивал по вот этой статье http://sys-admin.org/ru/node/30
работает без нареканий.
единственное чего не хватает это белого листа

Добавлено: 2007-01-06 21:25:29
Alex Keda
А я как раз белый лист реализовал
А вот грейлистинга этого непонимаю - вернее, не вникал - некогда пока

Добавлено: 2007-01-06 22:51:11
robi
lissyara писал(а):А я как раз белый лист реализовал
если не сложно поделись реализацией
lissyara писал(а):А вот грейлистинга этого непонимаю - вернее, не вникал - некогда пока
в смысле "не понимаю, не вникал "? видимо ты очень счастливый человек..... нету у тебя спама.
мне недавно его пришлось отрубить на пару дней.... результат потряс.... соотношение номальных писем к спаму на некоторых ящиках превысило соотношение 1 к 4 :(

Добавлено: 2007-01-06 23:12:16
Alex Keda
есть - куда ж без него
Тока мне название этой хреновины не нравицца - поэтому не смотрел даже.
У всех свои тараканы %)
===================
А белые листы - тока во вторник - щас с домашней машиной ковыряюсь :roll:

Добавлено: 2007-01-10 18:44:08
robi
lissyara писал(а): А белые листы - тока во вторник - щас с домашней машиной ковыряюсь :roll:
Этак вежливо напоминаю :)
Сам уже сделал но интересно как у тебя реализовано.

Добавлено: 2007-01-11 9:23:18
Alex Keda
ну так выкладывай. :))
==========
Днём, время будет - выложу...
==========
Заметим - уже не обещщаю точно сегодня :)

Добавлено: 2007-01-11 9:37:06
Alex Keda
Так. время всё же есть.
Имеем - транспорт:

Код: Выделить всё

remote_smtp:
  driver        = smtp
  # Это - необязательно :)
  headers_add   = "X-Descriptions: powered by www.lissyara.su"
  hosts_avoid_esmtp     =  ${lookup mysql{INSERT IGNORE INTO `sended_list` \
                        (`user_from`, `user_to`, `added_timestamp`, \
                        `last_mail_timestamp`, `mail_count`) VALUES \
                        ('${quote_mysql:$sender_address}', \
                        '${quote_mysql:$local_part@$domain}', \
                        UNIX_TIMESTAMP(), UNIX_TIMESTAMP(), '1') ON DUPLICATE \
                        KEY UPDATE `last_mail_timestamp` = UNIX_TIMESTAMP(), \
                        `mail_count` = `mail_count` + 1}}
Имеем - в acl_check_rcpt

Код: Выделить всё

# Вводим acl_m2 с нулевым значением
  warn  set acl_m2      = 0
# Проверяем - не было ли писем НА домен отправителя от наших юзеров.
# Если были - то потом, в фильтре, обнулим количество насчитанных очков.
  warn  condition       = ${if eq{${lookup mysql{SELECT 1 FROM `sended_list` \
                                WHERE `user_to` = \
                                '${quote_mysql:$sender_address}' AND `user_from` \
                                = '${quote_mysql:$local_part@$domain}' AND \
                                `last_mail_timestamp` < `last_mail_timestamp` \
                                + (60*24*60*60)}}}{1}{yes}{no}}

        condition       = ${lookup mysql{INSERT IGNORE INTO `domain_whitelist` \
                                (`domainname`, `domain_ip`, `added_timestamp`, \
                                `last_mail_timestamp`, `mail_count`) \
                                VALUES ('${quote_mysql:$sender_address_domain}', \
                                '${quote_mysql:$sender_host_address}', \
                                UNIX_TIMESTAMP(), UNIX_TIMESTAMP(), '1') ON \
                                DUPLICATE KEY UPDATE \
                                `last_mail_timestamp` = UNIX_TIMESTAMP(), \
                                `mail_count` = `mail_count` + 1}}
        hosts           = !+relay_from_hosts : *
        set acl_m2      = 1
        logwrite        = STAGE12: $sender_address ==> $local_part@$domain; setting acl_m2 = $acl_m2; WHITELIST for this addresses

# Переменная изменилась лишь если это были те же самые получатели,что и общались
# при внесении данных в транспорте. Для остальных этот домен так и остался
# без изменений. Соответственно надо сделать его и для остальных белым.
  warn  condition       = ${if eq{${lookup mysql{SELECT 1 FROM `domain_whitelist` \
                                WHERE `domain_ip` = \
                                '${quote_mysql:$sender_host_address}'}}}{1} \
                                {yes}{no}}
        hosts           = !+relay_from_hosts : *
        set acl_m2      = 1
        logwrite        = STAGE13: $sender_address ==> $local_part@$domain; setting acl_m2 = $acl_m2; WHITELIST for ALL domains
дампы таблиц:

Код: Выделить всё

-- 
-- Структура таблицы `domain_whitelist`
-- 

CREATE TABLE `domain_whitelist` (
  `id` int(9) NOT NULL auto_increment,
  `domainname` varchar(64) collate cp1251_bin NOT NULL,
  `domain_ip` varchar(16) collate cp1251_bin NOT NULL,
  `added_timestamp` int(32) NOT NULL,
  `last_mail_timestamp` int(32) NOT NULL,
  `mail_count` int(9) NOT NULL,
  PRIMARY KEY  (`id`),
  UNIQUE KEY `domainname` (`domainname`,`domain_ip`)
) ENGINE=MyISAM  DEFAULT CHARSET=cp1251 COLLATE=cp1251_bin COMMENT='Таблица белых доменов' AUTO_INCREMENT=1;

Код: Выделить всё

-- 
-- Структура таблицы `sended_list`
-- 

CREATE TABLE `sended_list` (
  `id` int(32) NOT NULL auto_increment,
  `user_from` varchar(64) collate cp1251_bin NOT NULL,
  `user_to` varchar(64) collate cp1251_bin NOT NULL,
  `added_timestamp` int(32) NOT NULL,
  `last_mail_timestamp` int(32) NOT NULL,
  `mail_count` int(6) NOT NULL,
  PRIMARY KEY  (`id`),
  UNIQUE KEY `user_from` (`user_from`,`user_to`)
) ENGINE=MyISAM  DEFAULT CHARSET=cp1251 COLLATE=cp1251_bin COMMENT='Таблица белых хостов' AUTO_INCREMENT=1;
Смысл содеянного - При отправке - в таблицу заносится данные от кого и кому ушло письмо (плюс дата и пара полей которые остались с тестов). При приёме проверяется - если идёт ответ от того юзера нашему - IP вносится в белый лист. Вторая проверка для остальных писем - есть ли такой домен в белом листе.
Действие - сбресывается переменная со спамерскими очками, но - это уже потом, примерно так:

Код: Выделить всё

# Сбрасываем спамерскую переменную, если домен в белом списке
        warn    condition       = ${if eq{$acl_m2}{1}{yes}{no}}
                set acl_m0      = 1
                logwrite        = Resetting acl_m0 $acl_m0 --> 0, host in whitelist
Ну и соответственно очки за спам не насчитываются, и задержка не вешается она у меня динамичкески - так:

Код: Выделить всё

  warn
#       condition       = ${if !eq{$acl_m0}{0}{yes}{no}}
#       condition       = ${if <{$acl_m0}{60}{yes}{no}}
        set acl_c0      = 5s
  warn
        #
        condition       = ${if !eq{$acl_m0}{0}{yes}{no}}
        condition       = ${if <{$acl_m0}{150}{yes}{no}}
        set acl_c0      = 15s
  warn
        # Вычисляем задержку на основании насчитанных за спам очков:
        condition       = ${if !eq{$acl_m0}{0}{yes}{no}}
        condition       = ${if >{$acl_m0}{150}{yes}{no}}
        set acl_c0      = ${eval:$acl_m0/10}s
  warn
        # ставим задержку в 0 секунд своим хостам и
        # дружественным сетям (соседняя контора :))
        hosts = +relay_from_hosts
        set acl_c0      = 0s
  warn
        # Ставим нулевую задержку хостам, с которми юзеры переписываются
        condition       = ${if eq{$acl_m2}{1}{yes}{no}}
        set acl_c0      = 0s
  warn
        # пишем в логи задержку (если оно вам надо)
        logwrite = Delay $acl_c0 (spam counter = $acl_m0; white host = $acl_m2) for $sender_host_name \
[$sender_host_address] with HELO=$sender_helo_name. Mail \
from $sender_address to $local_part@$domain.
        delay           = $acl_c0
=====================================================
Недоработки - таблицы пока не чистятся, в принципе - для облегчения жизи базе данных и серваку - лучше кроном раз в сутки...
Ограничения - MySQL5.0 и абове :) (может и на 4.1 будет - надо проверять - но на 4.0 не пашет - там не т функции

Код: Выделить всё

ON DUPLICATE KEY UPDATE