Скрипт для сбора портов подключения коммутаторов D-link, Zyxel и занесение их в NetK
Скрипт для сбора портов подключения коммутаторов D-link, Zyxel и занесение их в NetK
Скажу сразу, всё оборудование уже занесено в NetK - визуализатор сети, поэтому задача построения топологии сети не ставилась. Однако данные скрипты могут послужить основой для автоматической генерации топологии сети.
Итак, необходимо получить информацию по портам подключения коммутаторов:
1) порт вышестоящего коммутатора, к которому подключен текущий коммутатор;
2) порт (uplink) текущего коммутатора, к которому подключен вышестоящий коммутатор.
Пример портов подключения из NetK - коммутатор с IP-адресом 10.32.198.234 (назовем его текущий коммутатор) подключен к 26 порту вышестоящего коммутатора с IP-адресом 10.32.198.249. Порт подключения на текущем коммутаторе - 28.
Для реализации данной задачи буду перебирать MAC-адреса, полученные из таблицы коммутации оборудования. Предварительно необходимо пропинговать коммутатор (в случае, если к нему давно не было обращений), MAC-адрес которого необходимо найти, чтобы данный мак появился в arp таблице.
IP и MAC-адреса формировала sql запросом к базе данных NetK в следующем формате.
1. Для получения порта вышестоящего коммутатора, на который подключен текущий коммутатор:
10.32.198.249;00 1e 58 a0 dc 62; 10.32.198.234;1
где 10.32.198.249 - IP-адрес вышестоящего коммутатора, на котором необходимо найти MAC-адрес 00:1e:58:a0:dc:62 текущего коммутатора 10.32.198.134. Флаг 1 указывает, что производитель коммутатора 10.32.198.249 -D-link (флаг 0 - для коммутаторов Zyxel).
2. Для получения порта (uplink) текущего коммутатора, к которому подключен вышестоящий коммутатор:
10.32.198.234;00 1e 58 a8 56 2d; 10.32.198.249;1
где 10.32.198.234 - IP-адрес текущего коммутатора, на котором необходимо найти MAC-адрес 00:1e:58:a8:56:2d вышестоящего коммутатора 10.32.198.249. Флаг 1 указывает, что производитель коммутатора 10.32.198.234 -D-link (флаг 0 - для коммутаторов Zyxel).
IP-адреса коммутаторов D-link и Zyxel формировала отдельными списками ввиду большого количества оборудования - порядка 4-х тысяч.
Алгоритм сбора портов подключения коммутаторов:
1. Заходим по telnet на коммутатор, IP-адрес которого указан первым в строке.
2. Пингуем коммутатор, IP-адрес которого указан вторым в строке.
На коммутаторах D-link:
# ping $ip times 1 # logo
На коммутаторах Zyxel:
# ping $ip # exit
3. Выполняем команду snmpwalk из пакета Net-SNMP.
На коммутаторах D-link:
/usr/local/bin/snmpwalk -Osfn -c COMMUNITY -v2c $ip .1.3.6.1.2.1.17.7.1.2.2.1.2
Пример возвращаемого значения:
.1.3.6.1.2.1.17.7.1.2.2.1.2.2.0.28.240.40.57.191 = INTEGER: 21
где 0.28.240.40.57.191 - MAC-адрес в десятичной системе;
21 - номер порта.
На коммутаторах Zyxel:
/usr/local/bin/snmpwalk -Osfn -c COMMUNITY -v2c $ip .1.3.6.1.2.1.17.4.3.1.2
Пример возвращаемого значения:
.1.3.6.1.2.1.17.4.3.1.2.0.1.108.25.235.110 = INTEGER: 11
где 0.1.108.25.235.120 - MAC-адрес в десятичной системе;
11 - номер порта.
4. Сравниваем мак-адреса из таблицы коммутации с мак-адресом из строки и находим необходимый порт.
Скрипт сбора портов подключения коммутаторов - port.pl:
#!/usr/bin/perl use strict; use File::Copy; use Net::Telnet; my $storepath = './'; my $source_list = $storepath.'ip-mac.txt'; my $macaddr; my $result; my $oid_mac; my $oid_port; my $i_count=0; my $dumplog = './dump_port.log'; sub trim($) { $_[0]=~s/(^\s+)|(\s+$)|(\n$)//gs; return $_[0]; }; open (RW," >>$dumplog") or die "can't open dumplog: $!"; open (RL, $source_list) or die "can't open source list: $!"; while(<RL>){ my $ip= (split(/[;]/), $_)[0]; trim($ip); my $mac=(split(/[;]/), $_)[1]; trim($mac); my $ip_to= (split(/[;]/), $_)[2]; trim($ip_to); my $flag=(split(/[;]/), $_)[3]; trim($flag); print "-----------------------------------------\n"; print "start $ip-$ip_to-$mac\n"; my $username = 'LOGIN'; my $password = 'PASS'; my $dumplog_telnet = 'dump_telnet.log'; if ($ip =~ /^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/) { #Zyxel if($flag == 0){ print "telnet...start\n"; my $command_ping= 'ping '.$ip_to; my $command_ex='exit'; my $telnet = new Net::Telnet ( Timeout=>20, Errmode=> 'return', Dump_Log => $dumplog_telnet); if($telnet->open($ip)){ if($telnet->print($username)){ sleep(1); if($telnet->print($password)){ if($telnet->print($command_ping)){ sleep(1); if($telnet->print($command_ex)){ sleep(1); } }else{ print "error ping"; } }else{ print "error pass"; } }else{ print "error username"; } if($telnet->close){ print "telnet...end\n"; } }else{ print "error open"; } sleep(3); open DATA,"/usr/local/bin/snmpwalk -Osfn -c COMMUNITY -v 2c $ip .1.3.6.1.2.1.17.4.3.1.2|"; $oid_mac=""; $macaddr=""; $oid_port=""; while (<DATA>){ $oid_mac=(split(/[=]/), $_)[0]; trim($oid_mac); $oid_port=(split(/[ ]/), $_)[3]; trim($oid_port); if ($oid_mac =~ /^\.1\.3\.6\.1\.2\.1\.17\.4\.3\.1\.2\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/) { my $mac1=sprintf "%02lx",$1; my $mac2=sprintf "%02lx",$2; my $mac3=sprintf "%02lx",$3; my $mac4=sprintf "%02lx",$4; my $mac5=sprintf "%02lx",$5; my $mac6=sprintf "%02lx",$6; $macaddr=$mac1.' '.$mac2.' '.$mac3.' '.$mac4.' '.$mac5.' '.$mac6; trim($macaddr); } if ($macaddr =~ /$mac/) { $i_count=$i_count + 1; print "$i_count: $ip - $oid_port - $mac - $ip_to - $flag\n"; print RW "$ip;$oid_port;$mac;$ip_to;$flag\n"; } } }elsif($flag == 1){ #D-link print "telnet...start\n"; my $command_ping= 'ping '.$ip_to.' times 1'; my $command_ex='logo'; my $telnet = new Net::Telnet ( Timeout=>20, Errmode=> 'return', Dump_Log => $dumplog_telnet); if($telnet->open($ip)){ if($telnet->print($username)){ sleep(1); if($telnet->print($password)){ if($telnet->print($command_ping)){ sleep(1); if($telnet->print($command_ex)){ sleep(1); } }else{ print "error ping"; } }else{ print "error pass"; } }else{ print "error username"; } if($telnet->close){ print "telnet...end\n"; } }else{ print "error open"; } sleep(3); open DATA,"/usr/local/bin/snmpwalk -Osfn -c COMMUNITY -v 2c $ip .1.3.6.1.2.1.17.7.1.2.2.1.2|"; $oid_mac=""; $macaddr=""; $oid_port=""; while (<DATA>){ $oid_mac=(split(/[=]/), $_)[0]; trim($oid_mac); $oid_port=(split(/[ ]/), $_)[3]; trim($oid_port); if ($oid_mac =~ /^\.1\.3\.6\.1\.2\.1\.17\.7\.1\.2\.2\.1\.2\.\d{1,3}\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/) { my $mac1=sprintf "%02lx",$1; my $mac2=sprintf "%02lx",$2; my $mac3=sprintf "%02lx",$3; my $mac4=sprintf "%02lx",$4; my $mac5=sprintf "%02lx",$5; my $mac6=sprintf "%02lx",$6; $macaddr=$mac1.' '.$mac2.' '.$mac3.' '.$mac4.' '.$mac5.' '.$mac6; trim($macaddr); if ($macaddr =~ /$mac/) { $flag=1; $i_count=$i_count + 1; print "$i_count: $ip - $oid_port - $mac - $ip_to - $flag\n"; print RW "$ip;$oid_port;$mac;$ip_to;$flag\n"; } } } } } } close(RW); close(RL);
Результат можно наблюдать в файле dump_port.log. Формат записей:
10.32.198.249;26;00 1e 58 a0 dc 62; 10.32.198.234;1
где 26 - искомый порт.
Скрипт обновления порта подключения текущего коммутатора к вышестоящему в базе данных NetK
В примере выше для узла с IP-адресом 10.32.198.234 номер порта - 26. Пример входных данных:
10.32.198.249;26;00 1e 58 a0 dc 62; 10.32.198.234;1
update_port_to.php:
<?php include("./config.php"); $filename ="./dump_port.log"; $fp =fopen($filename, "r"); $pub = fread($fp, filesize($filename)); fclose($fp); $arr = array(); $arr = preg_split('/\n/', $pub,-1, PREG_SPLIT_NO_EMPTY); $count_port=0; foreach ($arr as $idx=> $val) { $count_port++; $knot_par = explode(";", $arr[$idx]); $knot_ip=trim($knot_par[3]); $knot_port=trim($knot_par[1]); mysql_query("LOCK TABLES `net` WRITE;"); $query_up = "UPDATE net SET port_to='$knot_port' where INET_NTOA(ip_for)='$knot_ip'"; if(!mysql_query($query_up)) { echo "error update"; } mysql_query("UNLOCK TABLES"); } echo"port $count_port"; ?>
Скрипт обновления порта подключения вышестоящего коммутатора к текущему в базе данных NetK
В примере выше для узла с IP-адресом 10.32.198.234 номер порта - 28. Пример входных данных:
10.32.198.234;28;00 1e 58 a8 56 2d; 10.32.198.249;1
update_port_for.php:
<?php include("./config.php"); $filename ="./dump_port.log"; $fp =fopen($filename, "r"); $pub = fread($fp, filesize($filename)); fclose($fp); $arr = array(); $arr = preg_split('/\n/', $pub,-1, PREG_SPLIT_NO_EMPTY); $count_port=0; foreach ($arr as $idx=> $val) { $count_port++; $knot_par = explode(";", $arr[$idx]); $knot_ip=trim($knot_par[0]); $knot_port=trim($knot_par[1]); mysql_query("LOCK TABLES `net` WRITE;"); $query_up = "UPDATE net SET port_for='$knot_port' where INET_NTOA(ip_for)='$knot_ip'"; if(!mysql_query($query_up)) { echo "error update"; } mysql_query("UNLOCK TABLES"); } echo"port $count_port"; ?>
Нажимая кнопку «Сохранить», я подтверждаю свою дееспособность, согласие на получение информации от NetK, согласие на обработку персональных данных в соответствии с Политикой конфиденциальности и Пользовательским соглашением.