mirror of
https://github.com/zeek/zeek.git
synced 2025-10-02 14:48:21 +00:00
184 lines
5.9 KiB
Perl
Executable file
184 lines
5.9 KiB
Perl
Executable file
#!@PERL@
|
|
|
|
##This script assumes that there are a lot more external IP Adresses
|
|
##than internal ones. It associates all IP adresses with a MAC Adress
|
|
##and tracks what MAC adress communicates with what other MAC adress.
|
|
|
|
use strict;
|
|
use IP4;
|
|
use Getopt::Std;
|
|
|
|
my $usage="localnetMac.pl -r <dumpfile> or
|
|
localnetMac.pl -t <ascii file>
|
|
options:
|
|
\t-a <aggregate up to bits>
|
|
\t-b <output bro-syntax internal nets to file>
|
|
\t-m do not ignore multicast IP addresses
|
|
\t-v output debug info
|
|
\nInput is taken either from plain or gzip compressed files.
|
|
Input formats:
|
|
\tlibpcap dump file containing ethernet packets
|
|
\tasci file containing <LinkLayerAdr1 LinkLayerAdr2 IPAdr1 IPAdr2> per line
|
|
\nNote: for libpcap inputs currently only ethernet is supported. Other link layer protocols should work if using ascii input.\n";
|
|
|
|
my %args;
|
|
getopts("a:b:mr:t:v", \%args);
|
|
my $aggto=0;
|
|
my $broout="";
|
|
my $decomp;
|
|
my $multicast = 0;
|
|
my $MCASTMIN=224;
|
|
my $MCASTMAX=239;
|
|
my $debug = 0;
|
|
if (!defined $args{r} and !defined $args{t}){die $usage;}
|
|
if (defined $args{a}){$aggto = $args{a};}
|
|
if (defined $args{b}){$broout=$args{b};}
|
|
if (defined $args{m}){$multicast = 1;}
|
|
if (defined $args{v}){$debug = 1;}
|
|
|
|
if($args{r}=~/gz$/ or $args{t}=~/gz$/){
|
|
$decomp = `which zcat`;
|
|
chomp($decomp);
|
|
if ($decomp eq ""){
|
|
$decomp = `which gzcat`;
|
|
chomp($decomp);
|
|
}
|
|
if ($decomp eq ""){
|
|
die "You need zcat or gzcat in your \$PATH in order to process compressed files\n";
|
|
}
|
|
}
|
|
|
|
my $fh;
|
|
if ($args{r} and $args{r}=~/gz$/){
|
|
open (IN, "$decomp $args{r} |../aux/adtrace/adtrace -|") or die "cannot execute $decomp $args{r} |../aux/adtrace/adtrace - : $!\n";
|
|
$fh = *IN;
|
|
}elsif($args{r}){
|
|
open (IN, "../aux/adtrace/adtrace $args{r}|") or die "cannot execute ./adtrace/adtrace $args{r}: $!\n";
|
|
$fh = *IN;
|
|
}elsif($args{t} and $args{t}=~/gz$/){
|
|
open (IN, "$decomp $args{t} |") or die "cannot execute $decomp $args{t} | : $!\n";
|
|
$fh = *IN;
|
|
}elsif($args{t} and $args{t} eq "-"){
|
|
$fh = *STDIN;
|
|
}else{
|
|
open (IN, "$args{t}") or die "cannot open $args{t}: $!\n";
|
|
$fh = *IN;
|
|
}
|
|
|
|
my %cMacs;
|
|
my %macIP;
|
|
|
|
#for statistics:
|
|
my $ips=0;
|
|
my $pkt=0;
|
|
|
|
my $line;
|
|
while ($line=<$fh>){
|
|
chomp($line);
|
|
$pkt++;
|
|
my ($sMac, $dMac, $sIP, $dIP)=split(/ /, $line);
|
|
|
|
if (!$multicast and $sIP=~/^(\d+)\./ and $1>=$MCASTMIN and $1<=$MCASTMAX){next;}
|
|
if (!$multicast and $dIP=~/^(\d+)\./ and $1>=$MCASTMIN and $1<=$MCASTMAX){next;}
|
|
|
|
$macIP{$sMac}->{count}++ if (!exists $macIP{$sMac}->{$sIP});
|
|
$macIP{$sMac}->{$sIP}++;
|
|
$macIP{$dMac}->{count}++ if (!exists $macIP{$dMac}->{$dIP});
|
|
$macIP{$dMac}->{$dIP}++;
|
|
|
|
$cMacs{join(" ", sort($sMac, $dMac))}++;
|
|
|
|
}
|
|
|
|
close ($fh);
|
|
|
|
foreach my $mac (keys %macIP){
|
|
$ips += $macIP{$mac}->{count};
|
|
}
|
|
|
|
printf ("observed %d MAC adresses\n", scalar(keys %macIP));
|
|
print (join ("\n", keys %cMacs));
|
|
print "\n";
|
|
print "observed $pkt packets and $ips distinct IP adresses\nLocal IP addresses:\n";
|
|
|
|
|
|
if ($broout){
|
|
open (OUT, "> $broout") or die "cannot open $broout: $!\n";
|
|
print OUT "### Local Networks automatically generated by localnetMAC.pl ###\n";
|
|
if ($aggto){
|
|
print OUT "### NOTE: Internal Networks have been aggregated up to /$aggto networks.\n";
|
|
print OUT "### NOTE: Therefore it may happen that some external Networks\n";
|
|
print OUT "### NOTE: are considered local\n";
|
|
}
|
|
print OUT "### file generated at ".localtime()." (local system-time)\n";
|
|
printf OUT ("### observed %d MAC adresses:\n###\t", scalar(keys %macIP));
|
|
print OUT (join ("\n###\t", keys %cMacs));
|
|
print OUT "\n";
|
|
print OUT "### observed $pkt packets and $ips distinct IP adresses\n";
|
|
print OUT "\n\n";
|
|
print OUT "\@load site\n\n";
|
|
print OUT "redef local_nets: set[subnet] = {\n";
|
|
}
|
|
|
|
foreach my $macPair (keys %cMacs){
|
|
my ($mac1, $mac2) = split(/ /, $macPair);
|
|
my %record1;
|
|
my %record2;
|
|
my ($smallRec, $bigRec);
|
|
$record1{mac} = $mac1;
|
|
$record2{mac} = $mac2;
|
|
$record1{hash} = $macIP{$mac1};
|
|
$record2{hash} = $macIP{$mac2};
|
|
$record1{count} = delete $record1{hash}->{count};
|
|
$record2{count} = delete $record2{hash}->{count};
|
|
$record1{masks} = [];
|
|
$record2{masks} = [];
|
|
|
|
if ($debug){
|
|
print "*** $mac1 ($record1{count}) ***\n";
|
|
print join("\n", sort keys %{$macIP{$mac1}});
|
|
print "\n*** $mac1 ($record1{count}) end***\n";
|
|
print "*** $mac2 ($record2{count}) ***\n";
|
|
print join("\n", sort keys %{$macIP{$mac2}});
|
|
print "\n*** $mac2 ($record2{count}) end***\n";
|
|
}
|
|
|
|
my @ips1 = map(getIPFromString($_), keys %{$record1{hash}});
|
|
$record1{ips} = \@ips1;
|
|
aggregateSinglesTo($record1{ips}, $record1{masks}, $aggto) if ($aggto);
|
|
my @ips2 = map(getIPFromString($_), keys %{$record2{hash}} );
|
|
$record2{ips} = \@ips2;
|
|
aggregateSinglesTo($record2{ips}, $record2{masks}, $aggto) if ($aggto);
|
|
|
|
if (scalar( @{$record1{ips}} ) < scalar( @{$record2{ips}} )){
|
|
$smallRec = \%record1;
|
|
$bigRec = \%record2;
|
|
}else{
|
|
$smallRec = \%record2;
|
|
$bigRec = \%record1;
|
|
}
|
|
if ($broout){
|
|
printf OUT ("\t# $smallRec->{mac}: %d(%d) IPs (considered local);\n\t# $bigRec->{mac}: %d(%d) IPs (considered extern)\n",
|
|
scalar( @{$smallRec->{ips}} ),$smallRec->{count},
|
|
scalar( @{$bigRec->{ips}} ), $bigRec->{count});
|
|
}
|
|
printf ("$smallRec->{mac}: %d(%d) IPs (considered local); $bigRec->{mac}: %d(%d) IPs (considered extern)\n",
|
|
scalar( @{$smallRec->{ips}} ),$smallRec->{count},
|
|
scalar( @{$bigRec->{ips}} ), $bigRec->{count});
|
|
@{$smallRec->{ips}} = map( getStringFromIP($_), @{$smallRec->{ips}} );
|
|
@{$smallRec->{masks}} = map( getPrefixFromMask($_), @{$smallRec->{masks}} );
|
|
for(my $i = 0; $i <= $#{$smallRec->{ips}}; $i++){
|
|
if ($smallRec->{masks}->[$i]){
|
|
print "$smallRec->{ips}->[$i]/$smallRec->{masks}->[$i]\n";
|
|
if ($broout){print OUT "\t $smallRec->{ips}->[$i]/$smallRec->{masks}->[$i],\n";}
|
|
}else{
|
|
print "$smallRec->{ips}->[$i]\n";
|
|
if ($broout){print OUT "\t $smallRec->{ips}->[$i]/32,\n";}
|
|
}
|
|
}
|
|
}
|
|
|
|
if ($broout){
|
|
print OUT "};\n";
|
|
close(OUT);
|
|
}
|