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. Вот их и стоит карантинить.
И так, окончательно определим стратегию:
Теперь о конфигурации 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 комментирует:
# 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 Снежана комментирует: