dhcdrop - Подавление DHCP серверов

Здесь можно задать вопросы не связанные с работой АСР. FreeBSD/Linux
lasik
Сообщения: 983
Зарегистрирован: Чт янв 10, 2008 5:20 pm
Откуда: Россия, Москва

Re: dhcdrop - Подавление DHCP серверов

Сообщение lasik »

какие вы не цивилизованые, свитчем, и все, желательно по рукам

ran
Сообщения: 2298
Зарегистрирован: Вс окт 21, 2007 2:29 pm

Re: dhcdrop - Подавление DHCP серверов

Сообщение ran »

lasik писал(а):какие вы не цивилизованые, свитчем, и все, желательно по рукам
аха... 48-портовым каталистом... по голове :D
Любой тупик - это тщательно замаскированный выход.

Abram
Сообщения: 157
Зарегистрирован: Чт мар 26, 2009 11:31 am
Контактная информация:

Re: dhcdrop - Подавление DHCP серверов

Сообщение Abram »

ran писал(а):
lasik писал(а):какие вы не цивилизованые, свитчем, и все, желательно по рукам
аха... 48-портовым каталистом... по голове :D
... директору. Ибо нефиг жалеть деньги на свитчи.

lasik
Сообщения: 983
Зарегистрирован: Чт янв 10, 2008 5:20 pm
Откуда: Россия, Москва

Re: dhcdrop - Подавление DHCP серверов

Сообщение lasik »

у мя тут умельци свитч d-link 3526 с такой переодичностью клали, еле нашел с какого порта, а так бы веселье продолжалось, но это я отвлекся.

против некоторых зверей, даже супер оборудование не поможет

NiTr0
Сообщения: 767
Зарегистрирован: Пт фев 08, 2008 4:46 pm

Re: dhcdrop - Подавление DHCP серверов

Сообщение NiTr0 »

Итак, таки портировал dhcdrop на LEAF, в связи с чем наваял к биллингу весьма полезный CGI костыль для уведомления саппорта о том, что некоему клиенту надо настучать по мозгам. Соответственно, с указанием кому и по каким причинам.
Итак, собссно dhcp.cgi:

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

#!/usr/bin/perl

BEGIN {
 my $libpath = '../';

 $sql_type='mysql';
 unshift(@INC, $libpath ."Abills/$sql_type/");
 unshift(@INC, $libpath);
 unshift(@INC, $libpath . 'libexec/');

 eval { require Time::HiRes; };
 if (! $@) {
    Time::HiRes->import(qw(gettimeofday));
    $begin_time = gettimeofday();
   }
 else {
    $begin_time = 0;
  }
}


require "config.pl";
require "Abills/defs.conf";
use Abills::SQL;
use Abills::Base;
use MIME::Base64 qw(encode_base64);
use CGI;
require Admins;
Admins->import();
my $admin = Admins->new($db, \%conf);

my $sql = Abills::SQL->connect($conf{dbtype},
                               $conf{dbhost},
                               $conf{dbname},
                               $conf{dbuser},
                               $conf{dbpasswd},
                               { CHARSET => ($conf{dbcharset}) ? $conf{dbcharset} : undef });
my $db = $sql->{db};
my $CONF;

$query = new CGI;

print "Content-Type: text/plain\n";
my $ua =  $ENV{'HTTP_USER_AGENT'};
my $i, $j, $id, $expire, $fio, $phone, $comments, $act_date, $actions, $mail_body;
my $q_ip=$query->param("ip");
my $q_mac=$query->param("mac");
my $q_iface=$query->param("iface");

my $support_mail='support@provider.com';
my $kill=1;


if ($q_ip && $q_mac && $q_iface && $ua =~ m/^Wget/) {
#if ($q_ip && $q_mac && $q_iface) {
    print "\n";
#    print "$ua\n";
    my $r_ip = $ENV{'REMOTE_ADDR'};

    #поиск мак-адреса в истории сторонних DHCP
    $admin->query($db,"SELECT COUNT(*)
                        FROM dhcphosts_unauthorized
                        WHERE mac='".$q_mac."'
                        AND seen>=CURDATE()
                        AND seen<CURDATE() + INTERVAL 1 DAY
                        ;");

    my $count=$admin->{list}->[0]->[0];

    #добавление записи в историю сторонних DHCP
    $admin->query($db,"INSERT INTO dhcphosts_unauthorized
                        (ip, mac, nas_ip, interface, seen)
                        VALUES(INET_ATON('".$q_ip."'),
                        '".$q_mac."',
                        INET_ATON('".$r_ip."'),
                        '".$q_iface."',
                        NOW());",'do');

    #найдено - разрешаем/запрещаем зафлудить сервер, и выходим
    if ($count) {
        print $kill;
        exit 0;
    }

    $mail_body="Системное сообщение от ".strftime( "%d.%m.%Y %H:%M:%S", localtime(time) )."\n\n";

    #поиск мак-адреса в таблице хостов
    $admin->query($db,"SELECT u.id, u.expire, pi.fio, pi.phone, pi.comments
                        FROM users u
                        LEFT JOIN users_pi pi ON u.uid=pi.uid
                        LEFT JOIN dhcphosts_hosts dh ON dh.uid=u.uid
                        WHERE dh.mac='".$q_mac."'
                        LIMIT 1;");
    if ($admin->{TOTAL}==0) {   #поиск по истории админ. операций
            $admin->query($db,"SELECT u.id, u.expire, pi.fio, pi.phone, pi.comments, aa.datetime, aa.actions, dh.mac
                        FROM users u
                        LEFT JOIN users_pi pi ON u.uid=pi.uid
                        LEFT JOIN admin_actions aa ON aa.uid=u.uid
                        LEFT JOIN dhcphosts_hosts dh ON dh.uid=u.uid
                        WHERE aa.actions LIKE '%".$q_mac."%'
                        AND aa.module='Dhcphosts'
                        ORDER BY aa.datetime DESC
                        LIMIT 1;");
    };
    if ($admin->{TOTAL}==0) {
        $mail_body.="Найден сторонний DHCP сервер, MAC адрес в базе отсутствует.\n";
        $mail_body.="Интерфейс: ".$q_iface."; MAC: ".$q_mac."; IP: ".$q_ip."\n";
        $mail_body.="Выполняется попытка зафлудить сервер...\n" if ($kill);
    }
    else {
        ($id, $expire, $fio, $phone, $comments, $act_date, $actions, $mac) = @{$admin->{list}->[0]};
        $mail_body.="Найден сторонний DHCP сервер, MAC которого присутствует в БД биллинга.\n";
        $mail_body.="Интерфейс: ".$q_iface." на роутере ".$r_ip."; MAC: ".$q_mac."; IP: ".$q_ip."\n";
        if ($act_date) {
            if (!$mac) {
                $mail_body.="Вероятный логин: ";
            } else {
                $mail_body.="Последний логин, где светился мак: "
            }
        } else {
            $mail_body.="Логин: ";
        }
        $mail_body.=$id."; дата окончания пакета - ".$expire."; данные о владельце: ".$fio.", тел. ".$phone."\n";
        $mail_body.="Доп. информация: ".$comments."\n";
        if ($act_date) {
            $mail_body.="В последний раз данный мак-адрес всплывал в истории админ. операций ".$act_date.":\n";
            $mail_body.=$actions."\n";
            $mail_body.="На данный момент у пользователя зарегистрирован мак ".$mac."\n" if ($mac);
        }
        $mail_body.="Выполняется попытка зафлудить сервер...\n" if ($kill);

    };
    sendmail("$conf{ADMIN_MAIL}", "$support_mail",'=?UTF-8?B?'.MIME::Base64::encode("Сторонний DHCP",'').'?=',
             "$mail_body", "$conf{MAIL_CHARSET}");
    print $kill;
    #print $mail_body;
}
else { #неправильные параметры или UserAgent
    print "Status: 301\n";
    # Или 301. Разница состоит в том, что по стандарту 301 значит "перемещён
    # навсегда", а 302 -- "перемещён временно"
    print "Location: /index.cgi\n";
    # URL должен быть указан абсолютный
    print "URI: /index.cgi\n\n"; # Для http/1.0
}
exit 0;
Дополнительная табличка в базе:

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

CREATE TABLE `dhcphosts_unauthorized` (
  `ip` int(10) unsigned NOT NULL default '0',
  `mac` varchar(17) NOT NULL default '00:00:00:00:00:00',
  `nas_ip` int(10) unsigned NOT NULL default '0',
  `interface` varchar(16) NOT NULL default '',
  `seen` datetime NOT NULL default '0000-00-00 00:00:00',
  UNIQUE KEY `date_mac` (`seen`,`mac`),
  KEY `date` (`seen`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT='Dhcphosts unauthorized DHCP servers';
Патч биллинга для отображения лога обнаруженных DHCP:

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

diff -aur abills-curr/Abills/modules/Dhcphosts/config /usr/abills/Abills/modules/Dhcphosts/config
--- abills-curr/Abills/modules/Dhcphosts/config	2007-11-15 11:29:42.000000000 +0200
+++ /usr/abills/Abills/modules/Dhcphosts/config	2010-01-05 22:54:48.000000000 +0200
@@ -12,7 +12,8 @@
 		               "12:11:$_HOSTS_ROUTES:dhcphosts_routes:NET_ID" => 5,
 		               "13:10:IP guard:dhcphosts_mac_block:"          => 5,
                    "14:13:Static:dhcphosts_mac_static:"           => 5,
-                   "15:0:DHCP:dhcphosts_monitor:"                 => 8
+                   "15:0:DHCP:dhcphosts_monitor:"                 => 8,
+                   "16:15:$_UADHCP:dhcphosts_ualog:"                  => 8
                    );
 
 %PERIODIC = (
diff -aur abills-curr/Abills/modules/Dhcphosts/webinterface /usr/abills/Abills/modules/Dhcphosts/webinterface
--- abills-curr/Abills/modules/Dhcphosts/webinterface	2009-09-07 16:44:18.000000000 +0300
+++ /usr/abills/Abills/modules/Dhcphosts/webinterface	2010-01-05 22:53:01.000000000 +0200
@@ -1198,4 +1198,60 @@
 
   return 0;	
 }
+
+#*******************************************************************
+# Show unauthorized log information
+#*******************************************************************
+sub dhcphosts_ualog {
+
+# if (! $conf{DHCPHOSTS_LEASES}) {
+#  	print $html->message('err', $_ERROR, "$_NOT_EXIST ". '$conf{DHCPHOSTS_LEASES}');
+#  	return 0;
+#  }
+ 
+
+   form_search({ SIMPLE => {
+   	                        "NAS IP"	=> 'NAS_IP',
+   	                        "$_INTERFACE"	=> 'INTERFACE',
+   	                        'IP'          => 'IP',
+                            'MAC'             => 'MAC',			
+   	                         }, 
+
+	            });
+
+   $LIST_PARAMS{DESC}='DESC' if (!defined($FORM{desc}));
+
+   my $list = $Dhcphosts->unauth_list({ %LIST_PARAMS });    
+	 
+   my $table = $html->table({ width    => '100%',
+                     			  caption    => "$_UA_DHCP_LOG",
+				          title      => ["$_TIME", "NAS IP", "IP", "MAC", "$_INTERFACE"],
+				          cols_align => ['left', 'right', 'right', 'right', 'right' ],
+				          ID         => 'LOG_UDHCP',
+                  			  qs         => $pages_qs,
+				          pages      => $Dhcphosts->{TOTAL}
+                          });
+
+	 
+   foreach my $line (@$list) {
+      $table->addrow($line->[0],
+                     $line->[1],
+                     $line->[2],
+                     $line->[3],
+                     $line->[4],
+                     );
+    }
+   print  $table->show();
+
+  $table = $html->table( { width      => '100%',
+                           cols_align => ['right', 'right'],
+                           rows       => [ [ "$_TOTAL:", $html->b($Dhcphosts->{TOTAL}) ] ]
+                       } );
+  print $table->show();
+
+   return 0;
+
+}
+
+
 1
diff -aur abills-curr/Abills/mysql/Dhcphosts.pm /usr/abills/Abills/mysql/Dhcphosts.pm
--- abills-curr/Abills/mysql/Dhcphosts.pm	2009-09-07 20:20:42.000000000 +0300
+++ /usr/abills/Abills/mysql/Dhcphosts.pm	2010-01-05 23:45:12.000000000 +0200
@@ -979,6 +979,98 @@
 }
 
 
+#**********************************************************
+# unauth_list()
+#**********************************************************
+sub unauth_list {
+  my $self=shift;
+  my ($attr)=@_;
+  
+  $SORT = ($attr->{SORT}) ? $attr->{SORT} : 0;
+  $DESC = ($attr->{DESC}) ? $attr->{DESC} : '';
+  $PG = ($attr->{PG}) ? $attr->{PG} : 0;
+  $PAGE_ROWS = ($attr->{PAGE_ROWS}) ? $attr->{PAGE_ROWS} : 25;
+
+  @WHERE_RULES = ();
+
+  if ($attr->{MAC}) {
+    push @WHERE_RULES, @{ $self->search_expr("$attr->{MAC}", 'STR', 'mac') };
+   }
+ 
+ if ($attr->{INTERFACE}) {
+   push @WHERE_RULES, @{ $self->search_expr("$attr->{INTERFACE}", 'STR', 'interface') };
+  }
+
+ if ($attr->{IP}) {
+    if ($attr->{IP} =~ m/\*/g) {
+      my ($i, $first_ip, $last_ip);
+      my @p = split(/\./, $attr->{IP});
+      for ($i=0; $i<4; $i++) {
+
+         if ($p[$i] eq '*') {
+           $first_ip .= '0';
+           $last_ip .= '255';
+          }
+         else {
+           $first_ip .= $p[$i];
+           $last_ip .= $p[$i];
+          }
+         if ($i != 3) {
+           $first_ip .= '.';
+           $last_ip .= '.';
+          }
+       }
+      push @WHERE_RULES, "(ip>=INET_ATON('$first_ip') and ip<=INET_ATON('$last_ip'))";
+     }
+    else {
+      push @WHERE_RULES, @{ $self->search_expr("$attr->{IP}", 'IP', 'ip') };
+    }
+  }
+
+ if ($attr->{NAS_IP}) {
+    if ($attr->{NAS_IP} =~ m/\*/g) {
+      my ($i, $first_ip, $last_ip);
+      my @p = split(/\./, $attr->{NAS_IP});
+      for ($i=0; $i<4; $i++) {
+
+         if ($p[$i] eq '*') {
+           $first_ip .= '0';
+           $last_ip .= '255';
+          }
+         else {
+           $first_ip .= $p[$i];
+           $last_ip .= $p[$i];
+          }
+         if ($i != 3) {
+           $first_ip .= '.';
+           $last_ip .= '.';
+          }
+       }
+      push @WHERE_RULES, "(nas_ip>=INET_ATON('$first_ip') and ip<=INET_ATON('$last_ip'))";
+     }
+    else {
+      push @WHERE_RULES, @{ $self->search_expr("$attr->{NAS_IP}", 'IP', 'nas_ip') };
+    }
+  }
+
+ $WHERE = ($#WHERE_RULES > -1) ? "WHERE " . join(' and ', @WHERE_RULES)  : '';
+
+  $self->query($db,"SELECT seen, INET_NTOA(nas_ip), INET_NTOA(ip), mac,  interface
+  
+  FROM dhcphosts_unauthorized
+   $WHERE 
+  ORDER BY $SORT $DESC LIMIT $PG, $PAGE_ROWS; ");
+
+  my $list = $self->{list};
+
+  $self->query($db,"SELECT count(*) FROM dhcphosts_unauthorized $WHERE;");
+
+  ($self->{TOTAL}) = @{ $self->{list}->[0] };
+  
+
+  return $list;
+
+}
 
 1
 
diff -aur abills-curr/language/english-utf8.pl /usr/abills/language/english-utf8.pl
--- abills-curr/language/english-utf8.pl	2008-09-17 00:28:19.000000000 +0300
+++ /usr/abills/language/english-utf8.pl	2010-01-05 22:57:24.000000000 +0200
@@ -5,6 +5, @@
 @MONTHES=('January', 'February', 'March', 'April', 'May', 'June', 'July', 'August',  'September', 'October', 'November', 'December');
 @WEEKDAYS=('Hollidays', 'Mo', 'Tu', 'Wn', 'Th', 'Fr', 'Sat', 'Sun');
 
+$_INTERFACE="Interface";
+$_UADHCP="Unauthorized DHCP";
 $_ADD='Add';
 $_GET='Get';
 $_GETED='Geted';
diff -aur abills-curr/language/russian-utf8.pl /usr/abills/language/russian-utf8.pl
--- abills-curr/language/russian-utf8.pl	2009-09-02 17:53:32.000000000 +0300
+++ /usr/abills/language/russian-utf8.pl	2010-01-05 22:56:40.000000000 +0200
@@ -1,3 +1,5 @@
+$_INTERFACE="Интерфейс";
+$_UADHCP="Сторонние DHCP";
 $_TOTAL="Всего";
 $_NOT_EXIST="Не существует";
 $_BRUTE_ATACK="Перебор паролей";
diff -aur abills-curr/language/ukraine-utf8.pl /usr/abills/language/ukraine-utf8.pl
--- abills-curr/language/ukraine-utf8.pl	2010-01-03 20:21:24.000000000 +0200
+++ /usr/abills/language/ukraine-utf8.pl	2010-01-05 22:55:48.000000000 +0200
@@ -1,3 +1,5 @@
+$_INTERFACE="Інтерфейс";
+$_UADHCP="Сторонні DHCP";
 $_LOG="Журнал";
 $_RECV="Отримано";
 $_TARIF_PLANS="Тарифні плани";

И собссно сам скрипт вызова dhcdrop:

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

#!/bin/sh

. /etc/dhcfind.conf

PATH=/bin:/sbin:/usr/bin:/usr/sbin

ifaces=`ip a|awk "/$IFACEEXP/"'{ sub(/:/,"",$2); print $2}'`

for i in $ifaces; do
        dhcp=`dhcdrop -t -i $i`
        if [ $? = 200 ]; then
                srvs=`echo "$dhcp"|sed 's/,//g'|awk '/YIP/ {print "ip=" $3 "&mac=" $8}'`
                for j in $srvs; do
                        wget "$URL?iface=$i&$j" -O /tmp/$i.res
                done
                res=`cat /tmp/$i.res`
                if [ "$res" = 1 ]; then
                        if [ "$AGGR" = 1  ]; then       #aggressive mode
                                echo "Unimplemented";
                        else
                                dhcdrop -i $i -y
                        fi
                fi
        fi
done
с конфигом:

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

IFACEEXP='(eth|vlan1)[0-9]+:'
AGGR=0
URL=http://billing.provider.com/dhcp.cgi
Последний раз редактировалось NiTr0 Вт янв 05, 2010 10:05 pm, всего редактировалось 2 раза.

dj_max_demon
Сообщения: 19
Зарегистрирован: Вт июн 23, 2009 9:02 am

Re: dhcdrop - Подавление DHCP серверов

Сообщение dj_max_demon »

не понял токо одного, как его использывать! напиши установку скрипта!

NiTr0
Сообщения: 767
Зарегистрирован: Пт фев 08, 2008 4:46 pm

Re: dhcdrop - Подавление DHCP серверов

Сообщение NiTr0 »

Копировать cgi в cg-bin,добавить в базу табличку, и по крону на роутере запускать шеллскрипт.

NiTr0
Сообщения: 767
Зарегистрирован: Пт фев 08, 2008 4:46 pm

Re: dhcdrop - Подавление DHCP серверов

Сообщение NiTr0 »

Немного изменил алгоритм работы (вместо фиксации факта обнаружения теперь в базе ведется журнал), и соответственно допилил веб-интерфейс для отображения журнала. Пост с кодом поправил.
Думаю, не только мне пригодится.

Ответить