poniżej zamieszcza skrypt, skanujący za pomocą MNDP otoczenie sieciowe
#!/usr/bin/perl -w
###############################################################################
#
# scan-mikrotik.pl v2.6.0
#
# scan utility for mikrotik
#
# 2011-03-27
# dodano uptime
#
# 2011-03-20
# mindc.net
###############################################################################
use strict;
use IO::Socket;
use Data::Dumper;
use Time::HiRes qw( usleep );
$|=1;
my %links;
print "scan-mikrotik.pl v2.6.0
link hw ip board sw uptime identity
--------------------------------------------------------------------------------
wait for 3 sec...\r";
open my $ph, "-|","ip a";
while ( <$ph> ) {
$links{$2} = $1 if m@\s(\S+)/\d+\s.*(eth\d+)@;
}
close $ph;
foreach my $link ( keys %links ) {
unless ( fork ) {
my $socket = IO::Socket::INET->new(
Proto => 'UDP',
PeerPort => 5678,
PeerAddr => inet_ntoa(INADDR_BROADCAST),
LocalAddr => $links{$link},
Broadcast => 1,
Reuse => 1
) or die "cannot bind socket $!\n";
my $data = {};
eval {
my $out = {};
local $SIG{ALRM} = sub {
foreach ( sort keys %$data ) {
my $o = $data->{$_};
printf("%s %17s %-16s %-10s %-7s %6s %s\n",
$link,
$o->{mac},
$o->{ip},
$o->{board},
$o->{sw},
sec2human($o->{uptime}),
$o->{identity}
);
}
print "\n" if keys %$data;
exit;
};
alarm 3;
open (STDIN,"tcpdump -i $link -lnqxt -s 1024 src port 5678 and proto UDP 2>/dev/null |");
usleep(100000);
$socket->send(pack("H8",0));
usleep(100000);
$socket->send(pack("H8",0));
usleep(100000);
$socket->send(pack("H8",0));
close $socket;
my $buffer = '';
my $i = 0;
while (<>) {
s/IP \S+.5678 > \S+ UDP, length \d+.*//g;
s/0x\d\d\d\d://g;
s/\s+//g;
$buffer .= $_;
if ( $_ =~ /^$/ && $buffer ne '' ) {
$i++;
my $out = mikrotik_header($buffer);
$data->{$out->{mac}} = $out;
$buffer = '';
}
}
alarm 0;
};
exit;
}
}
1 while ( wait() != -1);
system "killall tcpdump";
exit;
sub mikrotik_header {
my $buffer = shift;
#ip #udp #mikrotik
my @header = unpack("H4nH8H8NN nnnH4 H2H2S(H4n/a*)*", pack("H*",$buffer));
#ip header
shift @header; #ip1
shift @header; #ip_lenght
shift @header; #ip2
shift @header; #ip3
my $ip = shift @header; #ip_src
shift @header; #ip_dst
#udp header
shift @header; #udp_src_port
shift @header; #udp_dst_port
shift @header; #udp_lenght
shift @header; #udp_checksum
shift @header; #?
shift @header; #?
shift @header; #age?
my $out = {};
$out->{mac} = '';
$out->{identity} = '';
$out->{vendor} = '';
$out->{sw} = '';
$out->{board} = '';
$out->{key} = '';
$out->{uptime} = 0;
$out->{ip} = join(".",unpack("C4",pack("N",$ip)));
for ( my $i = 0; $i < @header ; $i += 2 ) {
my $type = $header[$i];
my $value = $header[$i+1];
$out->{mac} = uc join(":",unpack("(H2)6",$value)) if $type eq '0001';
$out->{identity} = $value if $type eq '0005';
$out->{vendor} = $value if $type eq '0008';
$out->{sw} = $value if $type eq '0007';
$out->{board} = $value if $type eq '000c';
$out->{key} = $value if $type eq '000b';
$out->{uptime} = unpack("L",$value) if $type eq '000a';
# $out->{unknown2} = $value if $type eq '000d';
}
return $out;
}
sub sec2human {
my $sec = shift;
return "" if $sec <= 0;
my $w = int($sec / 60 / 60 / 24 / 7);
my $d = int($sec / 60 / 60 / 24 % 7);
my $h = int($sec / 60 / 60 % 24);
my $m = int($sec / 60 % 60);
my $s = int($sec % 60);
if ( $w ) {
return sprintf("%dw%dd",$w,$d);
} elsif ( $d ) {
return sprintf("%dd%dh",$d,$h);
} elsif ( $h ) {
return sprintf("%dh%dm",$h,$m);
} elsif ( $m ) {
return sprintf("%dm%ds",$m,$s);
} else {
return "${s}s";
}
}
Działanie jest proste. Skrypt wysyła na każdym z interfejsów zapytanie
0x00000000
i zaczyna nasłuchiwać na odpowiedź w formacie MNDP. Warunkiem działania skrytpu jest istnienie co najmniej jednego adresu IP na danym interfejsie.
Niezbyt eleganckie rozwiązanie z
killall tcpdump
, ale nie mogłem sobie z tym poradzić, gdy nie zamykam
STDIN
. A może by tak
select
.
Brak komentarzy:
Prześlij komentarz