09.02.2008

Вести с полей. Разбираем урожай спама.

Неожиданно остро встала проблема спама. 500 и более писем в день, из которых фильтром отсеивается большая часть, но с десяток всё равно прорывается. А иногда, видимо когда спамеры придумывают как обходить фильтры, прорывается сразу 3-4 десятка в течение получаса. В общем напрягает. Такое количество сыплется потому, что на меня стоят редиректы системных почтовых ящиков (webmaster, hostmaster, postmaster, abuse) примерно с сотни доменов. Я бы уже и рад перенаправить их в /dev/null, но не привык отступать от RFC. По моему глубокому убеждению, интернет стал таким какой он есть (интероперабельным и глобальным) только потому, что соблюдались RFC. В случае с электронной почтой RFC 2142 явно требует существования в каждом домене как минимум адресов postmaster и abuse. Для нежелающих соблюдать это требование, даже придуман специальный чёрный список.

И вообще, отказаться от получения почты только потому, что туда сыплется спам - это не наш путь. Мне, например, гордость не позволяет. В войне со спамерами я не намерен капитулировать.

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

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

Но кто сказал, что в карантин должны попадать прямо таки все письма? В поисках аналога дебиановского greylistd для FreeBSD я наткнулся на вот такой метод. Вполне имеет право на быть. Если коротко, то в карантин отправляются только те письма, котороые приходят с хостов, попавших за всякие прегрешения в чёрные списки spamhaus, dsbl или любые другие. Красиво и функционально, на мой взгляд.

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

Подумав все эти мысли, я решил подключить на одном из почтовых серверов greylisting, но только для тех адресов, на которые особо злостно льётся спам.

Чтобы выявит эти адреса, был написан вот такой скрипт на python:


# -*- coding: utf-8 -*-

''' 

Анализатор фала в формате mbox 

Принимает единственный и обязательный параметр командной строки: путь к файлу.
Выводит стистику по электронным адресам, встречающимся в заголовках To: и Cc:
писем в анализируемом mbox.

'''

import re, mailbox, sys

email_reg = re.compile(
    r'[a-z0-9][a-z0-9_\.-]{0,}[a-z0-9]@[a-z0-9]'
    r'[a-z0-9_\.-]{0,}[a-z0-9][\.][a-z0-9]{2,4}')
total = 0

recipient_dict = {}
domain_dict = {}
local_part_dict = {}

for message in mailbox.mbox(sys.argv[1]):
    
    recipient_list = []
    recipient_list += email_reg.findall(message.get('To', ''))
    recipient_list += email_reg.findall(message.get('Cc', ''))
    
    for recipient in recipient_list:
        local_part, domain = recipient.split('@')
        domain_dict[domain] = domain_dict.get(domain, 0) + 1
        local_part_dict[local_part] = local_part_dict.get(local_part, 0) + 1
        recipient_dict[recipient] = recipient_dict.get(recipient, 0) + 1
        total += 1

def print_dict(res):
    res = map(lambda a: (a[1], a[0]), res.items())
    res.sort()
    res.reverse()
    res = map(lambda a: (a[1], a[0], float(a[0])/total*100), res)
    map(lambda a: a[2]>1 and sys.stdout.write("%40s %4d (%.1f%%)\n" % a), res)

print "\n%40s" % "Domains"
print "%40s" % "-------"
print_dict(domain_dict)
print "\n%40s" % "Local parts"
print "%40s" % "-----------"
print_dict(local_part_dict)
print "\n%40s" % "Addresses"
print "%40s" % "---------"
print_dict(recipient_dict)
print "\n"

Скрипту я скормил накопленный за неделю спам. Если честно, ничего нового не узнал. Но скрипт просто выкинуть - жалко. Так что пусть здесь живёт. Может кому-нибудь времени сэкономит.

Как и ожидалось, 82% моего спама сыпались локал-парты webmaster postmaster. Вот их и стоит карантинить.

И так, окончательно определим стратегию:

  • Создаём собственный «белый» список хостов. В него нужно включить крупных провайдеров (Yandex, Mail.ru, Google, Yahoo). Именно нужно, потому, что например Gmail время от времени попадает в чёрные списки.
  • Письмо для адресата с одним из локалпартов webmaster, postmaster, hostmaster, abuse, root - отправляем в грейлистинг, но только в том случае, если хост-отправитель ненаходится в нашем белом списке.
  • Письмо отправленное с хоста, занесённого как минимум в один из чёрных списков zen.spamhaus.org, list.dsbl.org - отправляем в грейлистинг, но только в том случае, если хост-отправитель ненаходится в нашем белом списке.

Теперь о конфигурации Exim. Лично я был сначала в полном недоумении относительно конфигурации разбитой на маленькие файлы. Зато потом я от неё пришел в полный восторг. Так что описывать я буду «разбитую» конфигурацию. Существует дока по специфике Exim 4 для Debian. Знатокам вражьей мовы советую.

Для начала устанавливаем greylistd:


$ sudo aptitude install greylistd

Никаких специфичных настроек он не требует. Как многое в Debian, «просто работает». Если понадобится тонкий тюнинг, можно посмотреть

/etc/greylistd/config
.

Если у вас ещё не определёно макро CHECK_RCPT_LOCAL_ACL_FILE, то сейчас это нужно сделать. Я привык подобные настройки класть в файл /etc/exim4/conf.d/main/00_local. В нём пишем:


CHECK_RCPT_LOCAL_ACL_FILE=/etc/exim4/acl.check_rcpt_local

Теперь в файле /etc/exim4/acl.check_rcpt_local:


    defer
        local_parts     =   webmaster : postmaster : hostmaster : abuse
        condition       =   ${readsocket{/var/run/greylistd/socket} \
                                {--grey ${mask:$sender_host_address/24} \
                                $sender_address $local_part@$domain} \
                                {5s}{}{false}}
        message         =   Your message is being greylisted because ip \
                            $sender_host_address is listed at $dnslist_domain \
                            ($dnslist_value: $dnslist_text). Please try again \
                            later.
        log_message     =   Greylisted ($sender_host_address is listed at \
                            $dnslist_domain ($dnslist_value: $dnslist_text)
        !hosts          =   ${if exists {/etc/exim4/local_host_whitelist} \
                            {net-iplsearch;/etc/exim4/local_host_whitelist} \
                            {}} : \
                            ${if exists {/var/lib/greylistd/whitelist-hosts} \
                            {/var/lib/greylistd/whitelist-hosts}{}}

    defer
        condition       =   ${readsocket{/var/run/greylistd/socket} \
                                {--grey ${mask:$sender_host_address/24} \
                                $sender_address $local_part@$domain} \
                                {5s}{}{false}}
        message         =   Your message is being greylisted because ip \
                            $sender_host_address is listed at $dnslist_domain \
                            ($dnslist_value: $dnslist_text). Please try again \
                            later.
        log_message     =   Greylisted ($sender_host_address is listed at \
                            $dnslist_domain ($dnslist_value: $dnslist_text)
        !hosts          =   ${if exists {/etc/exim4/local_host_whitelist} \
                            {net-iplsearch;/etc/exim4/local_host_whitelist} \
                            {}} : \
                            ${if exists {/var/lib/greylistd/whitelist-hosts} \
                            {/var/lib/greylistd/whitelist-hosts}{}}

Если у вас на сервере используется smtp-авторизация, то нужно сразу после каждого defer добавить :


        !authenticated  = *

Иначе ваши пользователи могут попасть в грейлистинг. Не думаю чтобы им понравилось.

Ну вот, в общих чертах всё. Если есть замечания - с удовольствием выслушаю.

Комментарии

09.02.08 18:37 uptimebox комментирует:

Забыл. Вот, что можно для начала попложить в /etc/exim4/local_host_whitelist:

# Google
64.233.160.0/19
66.249.64.0/19

# Microsoft
207.46.0.0/16

# RIPN
194.85.61.0/24

# Mail.ru
194.67.57.0/24
194.67.23.0/24

# Yandex
213.180.200.0/24
213.180.204.0/27
213.180.223.0/24

# Rambler
81.19.69.0/24
81.19.70.0/24

10.02.08 14:42 Anonymous комментирует:

пасибки, добрый человек!
Интересно!

25.04.08 12:10 Снежана комментирует:

Давно не сталкивалась со спамом, но последнее время уже задолбал, спасибо за полезную информацию, теперь спам не пройдет)