2016-02-16 3 views
1

Я новичок в Perl, и для практики я пишу простой скрипт perl для проверки моей домашней сети на наличие доступных IP-адресов и проверки их MAC-адресов, поставщиков и открытых портов для каждого из них. Вся эта информация, которую я хочу разместить в mysql db. Вот мой код:Perl скрипт для проверки сети

#!/usr/local/bin/perl 
use strict; 
use warnings; 
use Net::Ping; 
use Net::ARP; 
use DBI; 
use IO::Socket::PortState qw(check_ports); 
require config; 
my $proto = 'tcp'; 
my @ports = (21,22,23,80,8080); 
my $address; 
my $ping_timeout = 1; 
my $host; 
for my $i (18..21) 
{ 
     $host = "10.20.1.$i"; 
     my $timeout = 1; 
     my $pinger = Net::Ping->new('icmp', $timeout); 
     print "$host "; 
     if ($pinger->ping($host)) 
     { 
       my $mac = Net::ARP::arp_lookup("em0","$host"); 
       my $vendor = vendor_lookup($mac); 
       $vendor=~ s/^\s+|\s+$//g; 
       print "$mac $vendor "; 
       foreach my $port (@ports) 
       { 
         my($section, $ping_timeout, %porthash); 
         $porthash{$proto}{$port}{'name'} = $section; 
         check_ports($host, $ping_timeout, \%porthash); 
         my $open = $porthash{$proto}{$port}{'open'}; 
         if ($open) { 
           print "$port "; 
         } 
       } 
       print "\n"; 
     } 
} 

Если я запустить сценарий, я буду получать что-то вроде этого:

10.20.1.18 38:ea:a7:6f:d9:05 Hewlett Packard 80 8080 
10.20.1.19 fc:15:b4:31:77:76 Hewlett Packard 80 8080 
10.20.1.20 e8:39:35:25:dd:36 Hewlett Packard 22 80 

Моя проблема заключается в том, что я, кажется, не найти ответа, как объединить все, что ($ host, $ mac, $ vendor, $ port) и поместить его в базу данных, если мы поместим переменную $ port в @array, она будет иметь другой размер от других массивов.

Моя структура базы данных выглядит так:

+----+------------+-------------------+--------------+-----------------+---------------------+ 
| id | ip   | mac    | opened_ports | vendor   | date    | 
+----+------------+-------------------+--------------+-----------------+---------------------+ 
| 1 | 10.20.1.19 | fc:15:b4:31:77:76 | NULL   | Hewlett Packard | 2016-02-15 15:50:19 | 
| 2 | 10.20.1.20 | e8:39:35:25:dd:36 | NULL   | Hewlett Packard | 2016-02-15 15:50:19 | 
| 3 | 10.20.1.21 | 8c:dc:d4:5d:21:7b | NULL   | Hewlett Packard | 2016-02-15 15:50:19 | 
| 4 | 10.20.1.18 | 38:ea:a7:6f:d9:05 | NULL   | Hewlett Packard | 2016-02-15 16:02:09 | 
| 5 | 10.20.1.19 | fc:15:b4:31:77:76 | NULL   | Hewlett Packard | 2016-02-15 16:02:09 | 
| 6 | 10.20.1.20 | e8:39:35:25:dd:36 | NULL   | Hewlett Packard | 2016-02-15 16:02:10 | 
| 7 | 10.20.1.21 | 8c:dc:d4:5d:21:7b | NULL   | Hewlett Packard | 2016-02-15 16:02:10 | 
+----+------------+-------------------+--------------+-----------------+---------------------+ 

Это импортируется информация без информации для открытых портов.

+0

Вы уже определились с макетом базы данных? Пожалуйста, отредактируйте свой вопрос и поделитесь этим. Мне кажется, что вам нужно нормализовать вашу БД. – simbabque

+0

Я разделил структуру db. – user2642601

+0

Какой тип данных 'open_ports'? – simbabque

ответ

0

Ниже первоначального заявления печати print "$mac $vendor "; вы знаете хозяина макинтош поставщика и дату на этом этапе так prepare в заявлении вставки с заполнителем (?) для номера порта

Затем на линии, чтобы напечатать номер порта добавьте выполнить заявление с портом в положении заполнителя

Для отчетности использовать схему, как этот

create table scan (
    id int, 
    ip char(15), 
    mac char(20), 
    opened_ports int, 
    vendor varchar(255), 
    d datetime 
); 

здесь это данные тестов на основе Ваши примеры выше

INSERT INTO SCAN (Id,IP,MAC,OPENED_PORTS,VENDOR,D) VALUES(1,'10.20.1.19','fc:15:b4:31:77:76',25,'Hewlett Packard','2016-02-15 15:50:19'); 
INSERT INTO SCAN (Id,IP,MAC,OPENED_PORTS,VENDOR,D) VALUES(2,'10.20.1.20','e8:39:35:25:dd:36',80,'Hewlett Packard','2016-02-15 15:50:19'); 
INSERT INTO SCAN (Id,IP,MAC,OPENED_PORTS,VENDOR,D) VALUES(3,'10.20.1.21','8c:dc:d4:5d:21:7b',8080,'Hewlett Packard','2016-02-15 15:50:19'); 
INSERT INTO SCAN (Id,IP,MAC,OPENED_PORTS,VENDOR,D) VALUES(4,'10.20.1.18','38:ea:a7:6f:d9:05',137,'Hewlett Packard','2016-02-15 16:02:09'); 
INSERT INTO SCAN (Id,IP,MAC,OPENED_PORTS,VENDOR,D) VALUES(5,'10.20.1.19','fc:15:b4:31:77:76',443,'Hewlett Packard','2016-02-15 16:02:09'); 
INSERT INTO SCAN (Id,IP,MAC,OPENED_PORTS,VENDOR,D) VALUES(6,'10.20.1.20','e8:39:35:25:dd:36',8080,'Hewlett Packard','2016-02-15 16:02:10'); 
INSERT INTO SCAN (Id,IP,MAC,OPENED_PORTS,VENDOR,D) VALUES(7,'10.20.1.21','8c:dc:d4:5d:21:7b',22,'Hewlett Packard','2016-02-15 16:02:10'); 

и здесь есть запрос, который делает вывод в соответствии с требованиями

select ip,mac,GROUP_CONCAT(opened_ports) as port,vendor, d from scan group by ip; 
+1

Проблема в том, что может быть любое количество номеров портов для одного и того же IP-адреса. – reinierpost

+0

Каждая строка в базе данных уникальна по «id» не «ip», поэтому может быть вставлено несколько строк с одним и тем же ip – Vorsprung

+0

На самом деле вы этого не знаете. ОП не сказал этого в вопросе. Может также иметь уникальный индекс. – simbabque

1

Your database is not normalized. У вас есть базовое соотношение 1: N, где каждая строка может иметь ноль или более opened_ports.

Правильный способ справиться с этим - создать вторую таблицу и иметь N строк на id. Это будет выглядеть примерно так:

+-------+--------------+ 
| id_fk | opened_ports | 
+-------+--------------+ 
| 1 | 22   | 
| 1 | 80   | 
| 3 | 22   | 
+-------+--------------+ 

Затем удалите столбец opened_ports сюда главной таблицы и связать их через id.

В вашей программе Perl вам нужно сделать две вставки. Первый будет для большой таблицы, которая также создаст ваш (возможно, auto_increment) id. Вы можете получить это, вызвав $dbh->last_insert_id. После этого вы используете его для выполнения последующих вторых операторов вставки (или комбинированных) на маленькой таблице, содержащей порты.

Смежные вопросы