The OpenNET Project
 
Поиск (ключи):    ПРОГРАММЫ СТАТЬИ СОВЕТЫ ФОРУМ
  WIKI НОВОСТИ (+) MAN'ы ДОКУМЕНТАЦИЯ

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

Чисто интуитивно достаточно запустить tcpdump на исходящем канале, и
посмотреть, какие IP-адреса больше в
сего посылают SYN-пакетов на 25 порт.

  tcpdump -ni bridge0 'tcp[tcpflags] & tcp-syn != 0 and dst port 25'

В идеале это был бы ваш SMTP-сервер. В действительности вы увидите в основном
IP-адреса простых пользователей,
"одержимых бесами". Дело в том, что обычный спамбот создает SMTP-соединений во много раз больше 
вашего почтового сервера. Причем с разными IP-адресами.

В наши дни все нормальные почтовые сервера имеют PTR-запись DNS. Простые клиенты, напротив, 
такой записи обычно не имеют. Если почтовый сервер может устанавливать SMTP-соединения 
со множеством IP-адресов, то для простого клиента эта величина обычно не более 1-2 (например, 
пользование удаленными SMTP-серверами с лаптопа).

Исходя из этого, можно автоматически определять спамботов в нашей сети, и
блокировать их (например,
средствами IPFW). В качестве критерия оценки мы установили максимальное количество IP-адресов, 
с которыми каждый хост может общаться по SMTP в течение 5 минут. Для хостов с
реверсной записью DNS это 200,
для хостов без реверсной записи - 20. Если хост превышает этот лимит, он
попадает в черный список на сутки.

Нами написан Perl-скрипт, запускающий tcpdump на 5 минут, и анализирующий результаты. 
Хосты-нарушители заносятся в таблицу PostgreSQL для удобства персонала, и затем помещаются 
в таблицу IPFW. Правила файрвола блокируют все соединения на 25 порт с хостов,
находящихся в данной таблице.

Текст скрипта:

       #!/usr/local/bin/perl
       # dimss@stalin.lv 2009-08-20

       my $colltime = 300;    # How long to collect data
       my $rev_limit = 200;   # Remote IP limit for hosts with PTR record
       my $norev_limit = 20;  # Remote IP limit for hosts without PTR record
       my $table_no = 1; # Number of IPFW table

       use strict;
       use warnings;

       use POSIX ':signal_h';
       use Socket;
       use DBI;

       #
       # Collect data
       # Run tcpdump for some time
       #

       my $conns = {};

       my $mask = POSIX::SigSet->new( SIGALRM );
       my $action = POSIX::SigAction->new(
               sub {
                       system("killall tcpdump");
               },
               $mask
       );
       my $oldaction = POSIX::SigAction->new();
       sigaction(14, $action, $oldaction);

       alarm($colltime); # Run tcpdump for this amount of time
       open(T, "/usr/sbin/tcpdump -ni bridge0 'tcp[tcpflags] & tcp-syn != 0 " .
                       "and dst port 25' " .
                       "2>/dev/null |") or die;

       while(<T>){
               /\ ((\d+\.){3}\d+).+?((\d+\.){3}\d+)/;
               my $locip = $1;
               my $remip = $3;
               #print "$locip $remip\n";
               $conns->{$locip} ||= {};
               $conns->{$locip}->{$remip} ||= 1;
       }
       alarm(0);
       sleep(1);

       #
       # Analyze connections
       #


       $mask = POSIX::SigSet->new( SIGALRM );
       $action = POSIX::SigAction->new(
               sub {
                       die("Reverse lookup took too long");
               },
               $mask
       );
       $oldaction = POSIX::SigAction->new();
       sigaction(14, $action, $oldaction);

       alarm(60); # Reverse DNS lookups must complete within this period

       my %concount;
       my %bots;

       for my $locip (keys(%$conns)){
               #print("Loc IP: $locip\n");
               my $cnt = 0;
               for my $remip (keys(%{$conns->{$locip}})){
                       #print("  Rem IP: $remip\n");
                       $cnt++;
               }
               $concount{$locip} = $cnt;
       }

       for my $locip (sort {$concount{$b} <=> $concount{$a}} keys(%concount)){
               if($concount{$locip} > $norev_limit){
                       my $ip = inet_aton($locip);
                       my $name = gethostbyaddr($ip, AF_INET);
                       if($concount{$locip} > ($name ? $rev_limit : $norev_limit)){
                               #print("$locip: $concount{$locip} (" . ($name || '') . ")\n");
                               $bots{$locip} = $name;
                       }
               }
       }

       alarm(0);

       #
       # Update database
       #

       $mask = POSIX::SigSet->new( SIGALRM );
       $action = POSIX::SigAction->new(
               sub {
                       die("Database timeout");
               },
               $mask
       );
       $oldaction = POSIX::SigAction->new();
       sigaction(14, $action, $oldaction);

       alarm(15);

       my $dbh = DBI->connect("dbi:Pg:host=db.host.tld;dbname=spambot",
               "spambot", "passwd");
       if(!$dbh) {
               die("Cannot connect to DB");
       }

       my $query;
       my $sth;
       my $rv;
       for my $botip (keys(%bots)){
               #print "$botip\n";
               my $qname = $dbh->quote($bots{$botip});
               $query = "
                       update spambot_hosts set
                               active_till = now() + '1 days',
                               hostname = $qname
                       where ip = '$botip'
               ";
               $sth = $dbh->prepare($query);
               $rv = $sth->execute();
               if($rv != 1){
                       $query = "
                               insert into spambot_hosts
                               (ip, hostname, active_till)
                               values
                               ('$botip', $qname, now() + '1 days')
                       ";
                       $sth = $dbh->prepare($query);
                       $sth->execute();
               }
       }
       $query = "
               delete from spambot_hosts
               where active_till < now()
       ";
       $sth = $dbh->prepare($query);
       $sth->execute();

       #
       # Get full list of banned hosts from DB
       #

       $query = "
               select ip from spambot_hosts
       ";
       $sth = $dbh->prepare($query);
       $sth->execute();

       my %dlist;
       while(my $row = $sth->fetchrow_hashref){
               $dlist{$row->{ip}} = 1;
       }

       undef $dbh;
       alarm(0);

       #
       # Read list of banned hosts from kernel (ipfw) table
       #

       my %klist;
       if(open(KTABLE, "/sbin/ipfw table $table_no list|")){
               while(<KTABLE>){
                       chomp();
                       s/\/32//;
                       my ($prefix, $queue) = split();
                       $klist{$prefix} = 1;
               }
               close(KTABLE);
       }

       #
       # Update kernel table
       #

       for my $host (keys(%dlist)){
               unless($klist{$host}){
                       #print "Add $host\n";
                       system("/sbin/ipfw table $table_no add $host");
               }
       }

       for my $host (keys(%klist)){
               unless($dlist{$host}){
                       #print "Remove $host\n";
                       system("/sbin/ipfw table $table_no delete $host");
               }
       }

       exit;

Из /etc/ipfw.rules:

   #....
   ipfw -q add deny tcp from "table(1)" to any 25
   #....

У нас скрипт работает на шейпере, обслуживающем только заграничный канал.
Местный трафик им не анализируется
и не блокируется. При этом большая часть "хорошей" почты ходит именно по
местным каналам, но спамеры
спамят в основном по заграничному каналу. Так что лимиты вам наверняка придется
подстроить под себя.
Возможно, вам придется также реализовать "белый список", если у вас есть очень
активные SMTP-сервера.

На момент написания статьи в "расстрельном списке" несколько десятков хостов.
Жалоб за истекшие сутки
не поступало, хотя раньше их было множество.
 
24.08.2009 , Автор: Дмитрий Иванов
Раздел:    Корень / Администратору / Сетевые сервисы / Mail, почта / Борьба со спамом, фильтрация почты

Обсуждение [ Линейный режим | Показать все | RSS ]
 
  • 1.1, Аноним, 11:29, 24/08/2009 [ответить] [смотреть все]
  • +/
    фильтр PF в FreeBSD OpenBSD умеет самостоятельно вылавливать адреса, превышающие... весь текст скрыт [показать]
     
     
  • 2.2, Банзай, 11:38, 24/08/2009 [^] [ответить] [смотреть все] [показать ветку]  
  • +/
    Не умеет ... весь текст скрыт [показать] [показать ветку]
     
     
  • 3.6, Аноним, 13:51, 24/08/2009 [^] [ответить] [смотреть все]  
  • +/
    Умеет, конечно ... весь текст скрыт [показать]
     
     
  • 4.9, Щекн Итрч, 02:37, 25/08/2009 [^] [ответить] [смотреть все]  
  • +/
    Попробуйте и доложите Желательно с дешифрованными tpcdump ом логами, иллюструющ... весь текст скрыт [показать]
     
     
  • 5.14, ws, 11:57, 25/08/2009 [^] [ответить] [смотреть все]  
  • +/
    Где-то так table smtp_bruteforce persist block drop in quick from smtp_brute... весь текст скрыт [показать]
     
     
  • 6.23, pavlinux, 20:11, 25/08/2009 [^] [ответить] [смотреть все]  
  • +/
    А где ключевые слова умеет самостоятельно ... весь текст скрыт [показать]
     
  • 6.26, Щекн Итрч, 00:04, 26/08/2009 [^] [ответить] [смотреть все]  
  • +/
    Где-то или есть логи, иллюстрирующие гипотезу Можно фрагмент лога ... весь текст скрыт [показать]
     
     
  • 7.30, ws, 10:22, 26/08/2009 [^] [ответить] [смотреть все]  
  • +/
    У меня большой сети зомбируемых машин нет Поэтому оставлю вам это на самопрораб... весь текст скрыт [показать]
     
     
  • 8.32, настоящий_аноним, 15:39, 26/08/2009 [^] [ответить] [смотреть все]  
  • +/
    Мой друг, это же классика Про max-src-conn-rate pf hashlimit iptables знает... весь текст скрыт [показать]
     
     
  • 9.35, настоящий_аноним, 15:47, 26/08/2009 [^] [ответить] [смотреть все]  
  • +/
    Причем таймаут хранится для каждой записи отдельно ... весь текст скрыт [показать]
     
  • 9.37, ws, 16:46, 26/08/2009 [^] [ответить] [смотреть все]  
  • +/
    Естественно И применимая в текущей задаче Так и в pf таймауты в таблице выс... весь текст скрыт [показать]
     
     
  • 10.39, аноним, 01:03, 27/08/2009 [^] [ответить] [смотреть все]  
  • +/
    Если уж быть строгим и занудным до конца, то и iptables, и ipset - это всего лиш... весь текст скрыт [показать]
     
  • 2.3, Дима Иванов, 12:21, 24/08/2009 [^] [ответить] [смотреть все] [показать ветку]  
  • +/
    Здесь дело не в количестве соединений, а в количестве IP-адресов, с которыми уст... весь текст скрыт [показать] [показать ветку]
     
     ....нить скрыта, показать (12)

  • 1.4, Andrew, 12:43, 24/08/2009 [ответить] [смотреть все]  
  • +/
    Это, конечно, от ситуации зависит, но проще просто ЗАКРЫТЬ весь исходящий траффик на 25й порт, и проковырять его только для реальных почтовых серваков.

    Логика очень простая: кому действительно надо иметь выход на 25й порт, осознанно попросят его открыть, но их будет очень мало. Всем остальным это не надо, и они будут закрыты => боты обломаются. При этом надо, разумеется, _документировать_ эту политику.

     
     
  • 2.5, Дима Иванов, 12:45, 24/08/2009 [^] [ответить] [смотреть все] [показать ветку]  
  • +/
    Да, так было бы лучше всего Но пользователям этого не объяснить Т е увеличитс... весь текст скрыт [показать] [показать ветку]
     
     
  • 3.21, mr_gfd, 15:06, 25/08/2009 [^] [ответить] [смотреть все]  
  • +/
    На трипаки в сетке похер, а закрытый на выход 25й порт - это айс парсить maillo... весь текст скрыт [показать]
     
  • 1.7, jordan, 22:19, 24/08/2009 [ответить] [смотреть все]  
  • +/
    А есть чтото подобное для сервиса icq?
     
  • 1.8, настоящий_аноним, 00:59, 25/08/2009 [ответить] [смотреть все]  
  • +/
    Это же надо так мучаться В iptables это делается несколькими строчками Соз... весь текст скрыт [показать]
     
     
  • 2.24, andrew, 20:29, 25/08/2009 [^] [ответить] [смотреть все] [показать ветку]  
  • +/
    Нда Скрипт на двести строчек и три-четыре строчки на iptables и pf Наглядно... весь текст скрыт [показать] [показать ветку]
     
     
  • 3.27, Щекн Итрч, 00:05, 26/08/2009 [^] [ответить] [смотреть все]  
  • +/
    НЕ работают три-четыре строчки на iptables и pf НЕ работают Бабушку свою жит... весь текст скрыт [показать]
     
     
  • 4.31, аноним, 11:02, 26/08/2009 [^] [ответить] [смотреть все]  
  • +/
    А у меня - работают Причем далеко не на одном сервере Вопрос у кого из нас дв... весь текст скрыт [показать]
     
  • 4.33, настоящий_аноним, 15:44, 26/08/2009 [^] [ответить] [смотреть все]  
  • +/
    Полагаю, проблема не у iptables и pf , а у вас Где-то в области dev hands либ... весь текст скрыт [показать]
     
  • 1.10, shadow_alone, 04:52, 25/08/2009 [ответить] [смотреть все]  
  • +/
    Самое простое
    -A FORWARD -p tcp --dport 25 -j LOG --log-prefix smtpport:
    включить logwatch и получать почту с логом ежедневно, не гнушаясь просматривать.
     
  • 1.11, .snake, 05:12, 25/08/2009 [ответить] [смотреть все]  
  • +/
    -A FORWARD -s 192.168.0.0/16 -p tcp -m tcp --dport 25 -m state --state NEW -m recent --set --name SMTP
    -A FORWARD -s 192.168.0.0/16 -p tcp -m tcp --dport 25 -m state --state NEW -m recent --update --seconds 60 --hitcount 5 --name SMTP -j REJECT --reject-with icmp-port-unreachable

    Автоматически блокирует рассылку спама от клиентов. Как только спам прекращается почта начинает работать :)

     
     
  • 2.12, shadow_alone, 05:21, 25/08/2009 [^] [ответить] [смотреть все] [показать ветку]  
  • +/
    очень интересно, из-за кого-то одного будут страдать все - это во первых Во вто... весь текст скрыт [показать] [показать ветку]
     
     
  • 3.13, .snake, 06:23, 25/08/2009 [^] [ответить] [смотреть все]  
  • +/
    Страдать будет только тот кто спамит, проверено Префикс 16 указан для примера... весь текст скрыт [показать]
     
  • 3.16, настоящий_аноним, 13:11, 25/08/2009 [^] [ответить] [смотреть все]  
  • +/
    Мсье самый умный Мсье никогда не читает документацию Шагом марш читать man ipt... весь текст скрыт [показать]
     
     
  • 4.17, shadow_alone, 13:16, 25/08/2009 [^] [ответить] [смотреть все]  
  • +/
    Мсье не страдает такой хренью, ибо ... весь текст скрыт [показать]
     
     
  • 5.18, настоящий_аноним, 14:05, 25/08/2009 [^] [ответить] [смотреть все]  
  • +/
    Ибо считает, что лучше написать двадцать тормозных велосипедов по сто килобайт к... весь текст скрыт [показать]
     
     
  • 6.19, shadow_alone, 14:18, 25/08/2009 [^] [ответить] [смотреть все]  
  • +/
    совершенно неправильно сплошной, блин, офф топ лучше по русски - не по ... весь текст скрыт [показать]
     
     ....нить скрыта, показать (6)

  • 1.15, emp, 12:11, 25/08/2009 [ответить] [смотреть все]  
  • +/
    за прогу - зачёт. за ночь наловила 87 хостов. фикусы с iptables стоят на релее. но вот на исходящий поток от клиентов надо ставить чтото заносящее инфу в биллинг. чтоб тп по ночам спокойно могло удалить/приостановить бан клиенту, а не ждать админа чтобы он посмотрел в табличку.
     
     
  • 2.22, Дима Иванов, 15:17, 25/08/2009 [^] [ответить] [смотреть все] [показать ветку]  
  • +/
    >надо ставить чтото заносящее инфу в биллинг. чтоб тп по ночам спокойно могло >удалить/приостановить бан клиенту, а не ждать админа чтобы он посмотрел в табличку.

    Именно!!! Наконец кто-то понял мою задумку :)

     
  • 1.20, maap, 14:44, 25/08/2009 [ответить] [смотреть все]  
  • +/
    Я бы предложил анализировать коннтраки с ASSURED на 25 порту.
     
     
  • 2.36, настоящий_аноним, 15:52, 26/08/2009 [^] [ответить] [смотреть все] [показать ветку]  
  • +/
    >Я бы предложил анализировать коннтраки с ASSURED на 25 порту.

    Кстати вопрос: ctstatus анализирует все подключения или только related по conntrack?

     
  • 1.25, admin, 23:04, 25/08/2009 [ответить] [смотреть все]  
  • +/
    многабукаф в перле. может и красиво, но оч тяжело.
    у меня на шеле в 5 строк влезло.
     
     
  • 2.28, Щекн Итрч, 00:06, 26/08/2009 [^] [ответить] [смотреть все] [показать ветку]  
  • +/
    >многабукаф в перле. может и красиво, но оч тяжело.
    >у меня на шеле в 5 строк влезло.

    И не слабО их здесь привести?
    Что-то мешает? Шарики?

     
  • 2.34, настоящий_аноним, 15:46, 26/08/2009 [^] [ответить] [смотреть все] [показать ветку]  
  • +/
    >у меня на шеле в 5 строк влезло.

    У меня на iptables 3-4. У товарища выше на pf - 3. Что вы там так длинно пишете? ;)

     
  • 1.38, XoRe, 00:25, 27/08/2009 [ответить] [смотреть все]  
  • +/
    Скрипт, думаю, будет полезен Он хорошо подходит, когда нужно оповещать пользова... весь текст скрыт [показать]
     
  • 1.40, Илья Евсеев, 11:32, 03/09/2009 [ответить] [смотреть все]  
  • +/
    То же самое, только чуть короче :)
    http://sources.homelink.ru/spamblock/
     
  • 1.41, Kost, 15:53, 16/01/2012 [ответить] [смотреть все]  
  • +/
    Время записи в журнал client_connection_status_update_time 5m Задаём промеж... весь текст скрыт [показать]
     

    Ваш комментарий
    Имя:         
    E-Mail:      
    Заголовок:
    Текст:

     Добавить заметку
     Версия для печати
     
     Поиск заметки:
     

    Последние заметки
    - 12.05 Организация шифрованного бэкапа с помощью rdiff-backup, encfs и Dropbox
    - 11.05 Настройка беспроводного соединения в Debian GNU/Linux
    - 07.05 Использование Google Drive в Linux
    - 18.04 Использование нескольких сетевых стеков в Linux
    - 15.04 Восстановление стандартного KDE меню после его удаления (например, wine)
    - 11.04 Настройка gmirror при использовании GPT во FreeBSD 9
    - 09.04 Маршрутизатор на базе FreeBSD с приоритизация трафика средствами PF и ALTQ
    - 02.04 Частичное восстановление данных MySQL из бэкапа, созданного с использованием LVM
    - 21.03 Настройка DNSSEC в BIND 9.9
    - 17.03 Набор номера на Cisco IP Phone 7960/7940 из скрипта
    RSS | Следующие 15 записей >>


    ПОДПИШИСЬ НА ЖУРНАЛ Linux Format 2012!

    Журнал "Linux Format" (Линукс Формат)- Единственный в России и странах СНГ журнал на русском языке, посвящённый Linux и свободному ПО. Журнал для IT-директоров, IT-менеджеров, программистов, системных администраторов, учителей школ и преподавателей ВУЗов и всех пользователей ПК. В каждом выпуске: Новости индустрии OpenSource, обзоры новинок свободного ПО, обучающие и методические статьи.

    Каждый, кто оформит подписку, получает бонусы и подарки- объёмные наклейки на системный блок, диск с архивом номеров за 2005-2011 г.г. и ежемесячно электронную версию журнала в pdf-формате.

    Оформить подписку на год


      Закладки на сайте
      Проследить за страницей
    Created 1996-2012 by Maxim Chirkov  
    ДобавитьРекламаВебмастеруГИД  
    RUNNet TopList