From c447f9d09651381b8773381d925d168d817f7581 Mon Sep 17 00:00:00 2001 From: jack Date: Fri, 10 Mar 2017 15:11:05 +0100 Subject: [PATCH 1/4] Support optional IP to ASN mapping for netflow v5 Signed-off-by: jack --- bin/asstatd.pl | 36 ++++++++++++++++++++++++++++++++---- 1 file changed, 32 insertions(+), 4 deletions(-) diff --git a/bin/asstatd.pl b/bin/asstatd.pl index eb3b1d6..6759126 100755 --- a/bin/asstatd.pl +++ b/bin/asstatd.pl @@ -12,6 +12,7 @@ use IO::Socket; use RRDs; use Getopt::Std; use Scalar::Util qw(looks_like_number); +use ip2as; my %knownlinks; my %link_samplingrates; @@ -39,7 +40,7 @@ my $v10_templates = {}; my $sflow_server_port = 6343; use vars qw/ %opt /; -getopts('r:p:P:k:a:n', \%opt); +getopts('r:p:P:k:a:nm:', \%opt); my $usage = "$0 [-rpPka]\n". "\t-r \n". @@ -47,12 +48,14 @@ my $usage = "$0 [-rpPka]\n". "\t(-P \n". "\t-a - only required for sFlow\n". - "\t-n enable peer-as statistics\n"; + "\t-n enable peer-as statistics\n". + "\t-m IP<->ASN mapping\n"; my $rrdpath = $opt{'r'}; my $knownlinksfile = $opt{'k'}; my $myas_opt = $opt{'a'}; my $peerasstats = $opt{'n'}; +my $mapping = $opt{'m'}; die("$usage") if (!defined($rrdpath) || !defined($knownlinksfile)); @@ -129,6 +132,13 @@ if ($sflow_server_port > 0) { my ($him,$datagram,$flags); +if (defined($mapping)) { + ip2as::init($mapping); +} else { + #I don't use the mapping, to use an empty one + ip2as::init('/dev/null'); +} + # main datagram receive loop while (1) { while (my @ready = $sel->can_read) { @@ -160,6 +170,18 @@ while (1) { } } +sub replace_asn { + my $ip = shift; + my $asn = shift; + + my $new_asn = ip2as::getas4ip($ip); + if (defined($new_asn)) { + return $new_asn; + } else { + return $asn; + } +} + sub parse_netflow_v5 { my $datagram = shift; my $ipaddr = shift; @@ -173,8 +195,14 @@ sub parse_netflow_v5 { for (my $i = 0; $i < $count; $i++) { my $flowrec = substr($datagram, $v5_header_len + ($i*$v5_flowrec_len), $v5_flowrec_len); my @flowdata = unpack("NNNnnNNNNnnccccnnccN", $flowrec); - #print "ipaddr: " . inet_ntoa($ipaddr) . " octets: $flowdata[6] srcas: $flowdata[15] dstas: $flowdata[16] in: $flowdata[3] out: $flowdata[4] 4 \n"; - handleflow($ipaddr, $flowdata[6], $flowdata[15], $flowdata[16], $flowdata[3], $flowdata[4], 4, 'netflow'); + my $srcip = join '.', unpack 'C4', pack 'N', $flowdata[0]; + my $dstip = join '.', unpack 'C4', pack 'N', $flowdata[1]; + + my $srcas = replace_asn($srcip, $flowdata[15]); + my $dstas = replace_asn($dstip, $flowdata[16]); + + #print "ipaddr: " . inet_ntoa($ipaddr) . " octets: $flowdata[6] srcas: $srcas dstas: $dstas in: $flowdata[3] out: $flowdata[4] 4 \n"; + handleflow($ipaddr, $flowdata[6], $srcas, $dstas, $flowdata[3], $flowdata[4], 4, 'netflow'); } } From fc2a0bfb8c53f6dd35228d306f945df53314a873 Mon Sep 17 00:00:00 2001 From: jack Date: Fri, 10 Mar 2017 15:12:24 +0100 Subject: [PATCH 2/4] Update README Signed-off-by: jack --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index a2f1e5c..ca80adc 100644 --- a/README.md +++ b/README.md @@ -45,6 +45,7 @@ Prerequisites - libdbd-sqlite3-perl - one or more routers than can generate NetFlow v8/v9 AS aggregation records or sFlow samples +- ip2as.pm, for additional lookup (https://github.com/JackSlateur/perl-ip2as) Considerations ------------- From d0599e60aea56764cd8ca8a8d9c1c86cf4b46c3a Mon Sep 17 00:00:00 2001 From: jack Date: Thu, 16 Mar 2017 15:54:06 +0100 Subject: [PATCH 3/4] Support optional IP to ASN mapping for sFlow Signed-off-by: jack --- bin/asstatd.pl | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/bin/asstatd.pl b/bin/asstatd.pl index 6759126..026719e 100755 --- a/bin/asstatd.pl +++ b/bin/asstatd.pl @@ -591,6 +591,42 @@ sub parse_sflow { } } + # Extract src & dst IP from packet's header + my $srcip = undef; + my $dstip= undef; + my (undef, $ethertype, $ipdata) = unpack('a12H4a*', $sFlowSample->{'HeaderBin'}); + if($ethertype eq 8100){ + (undef, $ethertype, $ipdata) = unpack('nH4a*', $ipdata); + } + + if($ethertype eq '0800'){ + (undef, undef, undef, $srcip, $dstip) = unpack('nnB64NN', $ipdata); + $srcip = join '.', unpack 'C4', pack 'N', $srcip; + $dstip = join '.', unpack 'C4', pack 'N', $dstip; + } + + if($ethertype eq '86dd'){ + (undef, $sFlowSample->{HeaderDatalen}, undef, $srcip, $dstip) = unpack('NnnB128B128', $ipdata); + my @array_src = ( $srcip =~ m/......../g ); + my @array_dst = ( $dstip =~ m/......../g ); + $srcip = ''; + $dstip = ''; + for(my $x = 0; $x < scalar @array_src; $x = $x + 2){ + $srcip .= sprintf("%02x%02x:", oct("0b$array_src[$x]"), oct("0b$array_src[$x + 1]")); + } + chop($srcip); + + for(my $x = 0; $x < scalar @array_dst; $x = $x + 2){ + $dstip .= sprintf("%02x%02x:", oct("0b$array_dst[$x]"), oct("0b$array_dst[$x + 1]")); + } + chop($dstip); + } + + if (defined($srcip) && defined($dstip)){ + $srcas = replace_asn($srcip, $srcas); + $dstas = replace_asn($dstip, $dstas); + } + # Outbound packets have our AS number as the source (GatewayAsSource), # while inbound packets have 0 as the destination (empty AsPath). # Transit packets have "foreign" AS numbers for both source and From 2017097b305914ca73f7d315cc3bb9b1b6136e55 Mon Sep 17 00:00:00 2001 From: jack Date: Sun, 2 Apr 2017 14:08:17 +0200 Subject: [PATCH 4/4] Fix typo Signed-off-by: jack --- bin/asstatd.pl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/asstatd.pl b/bin/asstatd.pl index 026719e..fc1b05c 100755 --- a/bin/asstatd.pl +++ b/bin/asstatd.pl @@ -595,7 +595,7 @@ sub parse_sflow { my $srcip = undef; my $dstip= undef; my (undef, $ethertype, $ipdata) = unpack('a12H4a*', $sFlowSample->{'HeaderBin'}); - if($ethertype eq 8100){ + if($ethertype eq '8100'){ (undef, $ethertype, $ipdata) = unpack('nH4a*', $ipdata); }